[
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\n\nmulti-ecosystem-groups:\n  java:\n    schedule:\n      interval: daily\n\nupdates:\n  - package-ecosystem: docker\n    directories:\n      - \"/fabric-chaincode-docker\"\n      - \"/examples/fabric-contract-example-as-service\"\n    schedule:\n      interval: daily\n\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: daily\n\n  - package-ecosystem: gradle\n    multi-ecosystem-group: java\n    patterns:\n      - \"*\"\n    directories:\n      - \"/\"\n      - \"/fabric-chaincode-docker\"\n      - \"/examples/fabric-contract-example-as-service\"\n      - \"/examples/fabric-contract-example-gradle\"\n      - \"/examples/fabric-contract-example-gradle-kotlin\"\n      - \"/examples/ledger-api\"\n      - \"/fabric-chaincode-integration-test\"\n      - \"/fabric-chaincode-integration-test/src/contracts/bare-gradle\"\n      - \"/fabric-chaincode-integration-test/src/contracts/fabric-ledger-api\"\n      - \"/fabric-chaincode-integration-test/src/contracts/fabric-shim-api\"\n      - \"/fabric-chaincode-shim\"\n\n  - package-ecosystem: maven\n    multi-ecosystem-group: java\n    patterns:\n      - \"*\"\n    directories:\n      - \"/examples/fabric-contract-example-maven\"\n      - \"/fabric-chaincode-integration-test/src/contracts/bare-maven\"\n      - \"/fabric-chaincode-integration-test/src/contracts/wrapper-maven\"\n"
  },
  {
    "path": ".github/settings.yml",
    "content": "#\n# SPDX-License-Identifier: Apache-2.0\n#\n\nrepository:\n  name: fabric-chaincode-java\n  description: Hyperledger Fabric Contract and Chaincode implementation for Java\n    https://wiki.hyperledger.org/display/fabric\n  homepage: https://jira.hyperledger.org/issues/?jql=project+%3D+FAB+AND+component+%3D+fabric-chaincode-java\n  default_branch: main\n  has_downloads: true\n  has_issues: false\n  has_projects: false\n  has_wiki: false\n  archived: false\n  private: false\n  allow_squash_merge: false\n  allow_merge_commit: true\n  allow_rebase_merge: true\n"
  },
  {
    "path": ".github/workflows/pull_request.yml",
    "content": "# Copyright the Hyperledger Fabric contributors. All rights reserved.\n# SPDX-License-Identifier: Apache-2.0\n\nname: Pull request\n\non:\n  pull_request:\n    branches:\n      - main\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  test:\n    uses: ./.github/workflows/test.yml\n\n  scan:\n    uses: ./.github/workflows/scan.yml\n\n  pull-request:\n    needs: test\n    name: Pull request success\n    runs-on: ubuntu-latest\n    steps:\n      - run: \"true\"\n"
  },
  {
    "path": ".github/workflows/push.yml",
    "content": "# Copyright the Hyperledger Fabric contributors. All rights reserved.\n# SPDX-License-Identifier: Apache-2.0\n\nname: Push\n\non:\n  push:\n    branches:\n      - main\n  workflow_dispatch:\n\njobs:\n  test:\n    uses: ./.github/workflows/test.yml\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "# Copyright the Hyperledger Fabric contributors. All rights reserved.\n#\n# SPDX-License-Identifier: Apache-2.0\n\nname: Release\n\non:\n  push:\n    tags:\n      - \"v[0-9]+.[0-9]+.[0-9]+\"\n      - \"v[0-9]+.[0-9]+.[0-9]+-*\"\n  workflow_dispatch:\n\nenv:\n  IMAGE_NAME: ${{ github.repository_owner }}/fabric-javaenv\n\njobs:\n  publish-github:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      packages: write\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n      - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0\n        with:\n          distribution: \"temurin\"\n          java-version: 25\n      - uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0\n      - name: Publish to GitHub Packages\n        run: |\n          ./gradlew publishAllPublicationsToGitHubRepository\n        env:\n          ORG_GRADLE_PROJECT_signingKey: ${{ secrets.OSSRH_GPG_SECRET_KEY }}\n          ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n  publish-maven:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n      - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0\n        with:\n          distribution: \"temurin\"\n          java-version: 25\n      - uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0\n      - name: Publish to Maven Central\n        run: |\n          ./gradlew publishAggregationToCentralPortal\n        env:\n          ORG_GRADLE_PROJECT_signingKey: ${{ secrets.OSSRH_GPG_SECRET_KEY }}\n          ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}\n          ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVENCENTRAL_USERNAME }}\n          ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVENCENTRAL_PASSWORD }}\n\n  docker-build-push:\n    name: Push Docker image\n    runs-on: ${{ matrix.arch.runner }}\n    permissions:\n      contents: read\n      packages: write\n    strategy:\n      fail-fast: false\n      matrix:\n        arch:\n          - platform: linux-amd64\n            runner: ubuntu-24.04\n          - platform: linux-arm64\n            runner: ubuntu-24.04-arm\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n      - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0\n        with:\n          distribution: \"temurin\"\n          java-version: 25\n      - uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0\n      - name: Build the dependencies needed for the image\n        run: ./gradlew :fabric-chaincode-docker:copyAllDeps\n      - name: Get commit timestamp\n        run: echo \"SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)\" >> \"${GITHUB_ENV}\"\n      - name: Login to GitHub Container Registry\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: Login to Docker Hub\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0\n        with:\n          registry: docker.io\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0\n      - name: Build image\n        id: build\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0\n        with:\n          file: fabric-chaincode-docker/Dockerfile\n          context: fabric-chaincode-docker\n          outputs: type=registry,\"name=${{ format('ghcr.io/{0},docker.io/{0}', env.IMAGE_NAME) }}\",push-by-digest=true,name-canonical=true\n        env:\n          SOURCE_DATE_EPOCH: ${{ env.SOURCE_DATE_EPOCH }}\n      - name: Export digest\n        run: |\n          mkdir -p ${{ runner.temp }}/digests\n          digest=\"${{ steps.build.outputs.digest }}\"\n          touch \"${{ runner.temp }}/digests/${digest#sha256:}\"\n      - name: Upload digest\n        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1\n        with:\n          name: digest-${{ matrix.arch.platform }}\n          path: ${{ runner.temp }}/digests/*\n          if-no-files-found: error\n\n  docker-meta:\n    needs: docker-build-push\n    name: Publish Docker metadata\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      packages: write\n    strategy:\n      fail-fast: false\n      matrix:\n        registry:\n          - docker.io\n          - ghcr.io\n    steps:\n      - name: Download digests\n        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1\n        with:\n          path: ${{ runner.temp }}/digests\n          pattern: digest-*\n          merge-multiple: true\n      - name: Login to ${{ matrix.registry }}\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0\n        with:\n          registry: ${{ matrix.registry }}\n          username: ${{ matrix.registry == 'docker.io' && secrets.DOCKERHUB_USERNAME || github.actor }}\n          password: ${{ matrix.registry == 'docker.io' && secrets.DOCKERHUB_TOKEN || secrets.GITHUB_TOKEN }}\n      - name: Docker metadata\n        id: meta\n        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0\n        with:\n          images: ${{ matrix.registry }}/${{ env.IMAGE_NAME }}\n          tags: |\n            type=semver,pattern={{version}}\n            type=semver,pattern={{major}}.{{minor}}\n            type=semver,pattern={{major}}.{{minor}}.{{patch}}\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0\n      - name: Create and push manifest list\n        working-directory: ${{ runner.temp }}/digests\n        run: |\n          docker buildx imagetools create $(jq -cr '.tags | map(\"--tag \" + .) | join(\" \")' <<< \"${DOCKER_METADATA_OUTPUT_JSON}\") \\\n            $(printf '${{ matrix.registry }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)\n      - name: Inspect image\n        run: docker buildx imagetools inspect '${{ matrix.registry }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}'\n"
  },
  {
    "path": ".github/workflows/scan.yml",
    "content": "name: \"Scheduled vulnerability scan\"\r\n\r\non:\r\n  workflow_call:\r\n    inputs:\r\n      ref:\r\n        description: Branch, tag or SHA to scan.\r\n        type: string\r\n        required: false\r\n        default: \"\"\r\n\r\npermissions:\r\n  contents: read\r\n\r\njobs:\r\n  osv-scanner:\r\n    runs-on: ubuntu-latest\r\n    steps:\r\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\r\n          ref: ${{ inputs.ref }}\r\n      # Go needed for scanning of v2.5.5 and earlier\r\n      - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0\n        with:\r\n          go-version: stable\r\n          cache: false\r\n      - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0\n        with:\r\n          distribution: temurin\r\n          # Releases v2.5.7 and earlier do not support Java 25\r\n          java-version: 21\r\n      - uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0\n      - name: Scan\r\n        run: make scan\r\n"
  },
  {
    "path": ".github/workflows/schedule.yml",
    "content": "name: Scheduled build\n\non:\n  schedule:\n    - cron: \"5 4 * * 0\"\n  workflow_dispatch:\n\njobs:\n  main:\n    uses: ./.github/workflows/test.yml\n"
  },
  {
    "path": ".github/workflows/scheduled-scan.yml",
    "content": "name: \"Scheduled vulnerability scan\"\r\n\r\non:\r\n  schedule:\r\n    - cron: \"20 3 * * *\"\r\n  workflow_dispatch:\r\n\r\npermissions:\r\n  contents: read\r\n\r\njobs:\r\n  release-version:\r\n    name: Get latest release tag\r\n    runs-on: ubuntu-latest\r\n    outputs:\r\n      tag_name: ${{ steps.tag-name.outputs.value }}\r\n    steps:\r\n      - id: tag-name\r\n        run: echo \"value=$(curl --location --silent --fail \"https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/latest\" | jq --raw-output '.tag_name')\" >> \"${GITHUB_OUTPUT}\"\r\n\r\n  scan-release:\r\n    name: Scan ${{ needs.release-version.outputs.tag_name }}\r\n    needs: release-version\r\n    uses: ./.github/workflows/scan.yml\r\n    with:\r\n      ref: ${{ needs.release-version.outputs.tag_name }}\r\n\r\n  scan-latest:\r\n    name: Scan latest\r\n    uses: ./.github/workflows/scan.yml\r\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "# Copyright the Hyperledger Fabric contributors. All rights reserved.\n#\n# SPDX-License-Identifier: Apache-2.0\n\nname: Test\n\non:\n  workflow_call:\n    inputs:\n      ref:\n        default: \"\"\n        required: false\n        type: string\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          ref: ${{ inputs.ref }}\n      - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0\n        with:\n          distribution: temurin\n          java-version: 25\n      - uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0\n      - name: Build and Unit test\n        run: ./gradlew :fabric-chaincode-shim:build\n\n  intergationtest:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          ref: ${{ inputs.ref }}\n      - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0\n        with:\n          distribution: temurin\n          java-version: 25\n      - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0\n        with:\n          node-version: \"lts/*\"\n      - uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0\n      - name: Populate chaincode with latest java-version\n        run: |\n          ./gradlew -I $GITHUB_WORKSPACE/fabric-chaincode-integration-test/chaincodebootstrap.gradle -PchaincodeRepoDir=$GITHUB_WORKSPACE/fabric-chaincode-integration-test/src/contracts/fabric-shim-api/repository publishShimPublicationToFabricRepository\n          ./gradlew -I $GITHUB_WORKSPACE/fabric-chaincode-integration-test/chaincodebootstrap.gradle -PchaincodeRepoDir=$GITHUB_WORKSPACE/fabric-chaincode-integration-test/src/contracts/fabric-ledger-api/repository publishShimPublicationToFabricRepository\n          ./gradlew -I $GITHUB_WORKSPACE/fabric-chaincode-integration-test/chaincodebootstrap.gradle -PchaincodeRepoDir=$GITHUB_WORKSPACE/fabric-chaincode-integration-test/src/contracts/bare-gradle/repository publishShimPublicationToFabricRepository\n          ./gradlew -I $GITHUB_WORKSPACE/fabric-chaincode-integration-test/chaincodebootstrap.gradle -PchaincodeRepoDir=$GITHUB_WORKSPACE/fabric-chaincode-integration-test/src/contracts/bare-maven/repository publishShimPublicationToFabricRepository\n          ./gradlew -I $GITHUB_WORKSPACE/fabric-chaincode-integration-test/chaincodebootstrap.gradle -PchaincodeRepoDir=$GITHUB_WORKSPACE/fabric-chaincode-integration-test/src/contracts/wrapper-maven/repository publishShimPublicationToFabricRepository\n      - name: Ensure that the Peer/weft tools are available\n        run: |\n          curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/main/scripts/install-fabric.sh | bash -s -- binary\n          npm install -g @hyperledger-labs/weft\n\n          # set the path and cfg env var for the rest of the step\n          echo \"FABRIC_CFG_PATH=$GITHUB_WORKSPACE/config\" >> $GITHUB_ENV\n          echo \"$GITHUB_WORKSPACE/bin\" >> $GITHUB_PATH\n      - name: versions\n        run: |\n          peer version\n          weft --version\n      - name: Integration Tests\n        run: ./gradlew :fabric-chaincode-integration-test:build\n\n  docker:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          ref: ${{ inputs.ref }}\n      - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0\n        with:\n          distribution: temurin\n          java-version: 25\n      - uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0\n      - name: Build Docker image\n        run: ./gradlew :fabric-chaincode-docker:buildImage\n"
  },
  {
    "path": ".gitignore",
    "content": "/.settings/\n/.project\n*.log\n*.swp\n.gradletasknamecache\n.classpath\n**/bin/\n/build/\nbuild/*\nsettings-gradle.lockfile\nconfig/\n\n_cfg\nrepository\n\n.env\n\n.gradle\n/build/\nout/\ngradle.lockfile\n!gradle/wrapper/gradle-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\nnbproject/private/\nbuild/\nnbbuild/\ndist/\nnbdist/\n.nb-gradle/\n\nlocal-config.yaml\ngradle.properties\n.vscode/\n\n### Jekyll ###\n.sass-cache\n_site\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\nNotable changes in each release are documented on the project's [GitHub releases](https://github.com/hyperledger/fabric-chaincode-java/releases) page. Change history from previous releases is retained below.\n\n## v2.5.0\nThu Dec  8 09:02:17 GMT 2022\n\n* [94cfadee](https://github.com/hyperledger/fabric-chaincode-java/commit/94cfadee) Move inactive maintainers to emeritus status\n* [37bebee7](https://github.com/hyperledger/fabric-chaincode-java/commit/37bebee7) Adjust to using the Temurin JVM\n* [0c9f44fb](https://github.com/hyperledger/fabric-chaincode-java/commit/0c9f44fb) Basic github actions workflow\n* [d15f2cd1](https://github.com/hyperledger/fabric-chaincode-java/commit/d15f2cd1) Update pom.xml\n* [1fba41b2](https://github.com/hyperledger/fabric-chaincode-java/commit/1fba41b2) Remove unrequired Maven wrapper directory Update Maven wrapper to latest version\n* [3a2db82d](https://github.com/hyperledger/fabric-chaincode-java/commit/3a2db82d) Bump version to 2.5.0\n* [35eabb0a](https://github.com/hyperledger/fabric-chaincode-java/commit/35eabb0a) PurgePrivateData\n* [80a36ee4](https://github.com/hyperledger/fabric-chaincode-java/commit/80a36ee4) Swap to using the published fabric-protos libraries\n* [dd551979](https://github.com/hyperledger/fabric-chaincode-java/commit/dd551979) Update MAINTAINERS.md\n* [f25df1b6](https://github.com/hyperledger/fabric-chaincode-java/commit/f25df1b6) Add test for Logger.debug\n* [d1d093b4](https://github.com/hyperledger/fabric-chaincode-java/commit/d1d093b4) Regular Maintainece Task\n* [22c722fe](https://github.com/hyperledger/fabric-chaincode-java/commit/22c722fe) Update README.md\n* [2c35c3ed](https://github.com/hyperledger/fabric-chaincode-java/commit/2c35c3ed) JSONPropertyIgnore only works on getter\n* [02d1485a](https://github.com/hyperledger/fabric-chaincode-java/commit/02d1485a) Change from RocketChat to Discord\n* [5608879e](https://github.com/hyperledger/fabric-chaincode-java/commit/5608879e) Temporarily remove nightly publish & Fix PR build\n* [d13d3070](https://github.com/hyperledger/fabric-chaincode-java/commit/d13d3070) Fix transaction serializer usage\n* [5388349d](https://github.com/hyperledger/fabric-chaincode-java/commit/5388349d) Remove the log4j dependency\n\n## v2.4.1\nMon Dec 13 11:50:31 GMT 2021\n\n* [bf054cb0](https://github.com/hyperledger/fabric-chaincode-java/commit/bf054cb0) Add a brief example for the -as-a-service\n* [f9ada8f5](https://github.com/hyperledger/fabric-chaincode-java/commit/f9ada8f5) Chaincode-as-a-service main bootstrap method\n\n## 2.4.0\nFri Nov 26 08:21:40 GMT 2021\n\nRelease 2.4.0 \n\n## v2.4.0-beta\nFri 13 Aug 2021 16:43:31 CEST\n\n* [292c4ebe](https://github.com/hyperledger/fabric-chaincode-java/commit/292c4ebe) Update the build.gradle for publishing\n\n## v2.3.1\nWed 21 Jul 2021 11:20:03 BST\n\n* [6be7a724](https://github.com/hyperledger/fabric-chaincode-java/commit/6be7a724) Integration tests extended\n* [66e25ea9](https://github.com/hyperledger/fabric-chaincode-java/commit/66e25ea9) NettyGrpcServer -- support mutual TLS\n* [1128e7b2](https://github.com/hyperledger/fabric-chaincode-java/commit/1128e7b2) NettyGrpcServer: logger->LOGGER\n* [b7b4ef12](https://github.com/hyperledger/fabric-chaincode-java/commit/b7b4ef12) NettyGrpcServer -- reformat code\n* [3a98fc5e](https://github.com/hyperledger/fabric-chaincode-java/commit/3a98fc5e) NettyGrpcServer -- configure ALPN\n* [63c12ffa](https://github.com/hyperledger/fabric-chaincode-java/commit/63c12ffa) NettyGrpcServerTest -- improve startAndStopTlsPassword, startAndStopTlsWithoutPassword test cases\n* [5046eb79](https://github.com/hyperledger/fabric-chaincode-java/commit/5046eb79) Bump logback-classic in /examples/fabric-contract-example-maven\n* [ab2a166d](https://github.com/hyperledger/fabric-chaincode-java/commit/ab2a166d) added tests\n* [25706938](https://github.com/hyperledger/fabric-chaincode-java/commit/25706938) Add additional contracts for deployment test\n* [e096d4f7](https://github.com/hyperledger/fabric-chaincode-java/commit/e096d4f7) Review ideas\n* [7645bb9d](https://github.com/hyperledger/fabric-chaincode-java/commit/7645bb9d) Move to use Maven Wrapper\n* [d212e2a7](https://github.com/hyperledger/fabric-chaincode-java/commit/d212e2a7) Upgrade gradle to v7\n* [f1d6b7da](https://github.com/hyperledger/fabric-chaincode-java/commit/f1d6b7da) Gradle wrapper updated to the latest version\n* [3f190ef5](https://github.com/hyperledger/fabric-chaincode-java/commit/3f190ef5) Transaction metadata tags updated\n* [0d0c9280](https://github.com/hyperledger/fabric-chaincode-java/commit/0d0c9280) Update \"master\" branch references to \"main\"\n* [ca69f15d](https://github.com/hyperledger/fabric-chaincode-java/commit/ca69f15d) Fix link in SECURITY.md\n* [4c6cbf47](https://github.com/hyperledger/fabric-chaincode-java/commit/4c6cbf47) Correct condition\n* [76c7fe45](https://github.com/hyperledger/fabric-chaincode-java/commit/76c7fe45) Cleanup files\n* [70bdd194](https://github.com/hyperledger/fabric-chaincode-java/commit/70bdd194) Add in publishing of the nightly master branch drivers\n* [b51eac20](https://github.com/hyperledger/fabric-chaincode-java/commit/b51eac20) Change FABRIC_VERSION to latest tag\n* [28dfb24b](https://github.com/hyperledger/fabric-chaincode-java/commit/28dfb24b) fix fabric-contract-example-maven/pom.xml\n* [ff48941c](https://github.com/hyperledger/fabric-chaincode-java/commit/ff48941c) Logging Tests Reset Correctly\n* [cc31ae01](https://github.com/hyperledger/fabric-chaincode-java/commit/cc31ae01) [FABCJ-214](https://jira.hyperledger.org/browse/FABCJ-214) - Java chaincode gRPC server\n* [06f72193](https://github.com/hyperledger/fabric-chaincode-java/commit/06f72193) Fix \"build shadowJar\" error\n* [278e9f8e](https://github.com/hyperledger/fabric-chaincode-java/commit/278e9f8e) [FABCJ-187](https://jira.hyperledger.org/browse/FABCJ-187) Add max inbound msg size configuration\n* [bf4f30aa](https://github.com/hyperledger/fabric-chaincode-java/commit/bf4f30aa) Fix javadoc build\n* [9e403b6d](https://github.com/hyperledger/fabric-chaincode-java/commit/9e403b6d) Fix JavaDoc link to Compatibility documentation\n* [57678eea](https://github.com/hyperledger/fabric-chaincode-java/commit/57678eea) Bump version to 2.3.1\n* [91e6001d](https://github.com/hyperledger/fabric-chaincode-java/commit/91e6001d) [FABCJ-290](https://jira.hyperledger.org/browse/FABCJ-290) Add release guide\n* [0deb7e0d](https://github.com/hyperledger/fabric-chaincode-java/commit/0deb7e0d) [FABCJ-293](https://jira.hyperledger.org/browse/FABCJ-293) Remove gradle from image\n* [2dfe17c1](https://github.com/hyperledger/fabric-chaincode-java/commit/2dfe17c1) [FABCJ-291](https://jira.hyperledger.org/browse/FABCJ-291) Startkey needs additional checks For the open ended query, the start and empty keys are empty from the chaincode. However, in the shim, if the start key is an empty key, it is replaced with 0x01  which is nothing but a namespace for the non-composite key.\n* [21d81193](https://github.com/hyperledger/fabric-chaincode-java/commit/21d81193) Update doc links\n* [78ed0157](https://github.com/hyperledger/fabric-chaincode-java/commit/78ed0157) [FABCJ-288](https://jira.hyperledger.org/browse/FABCJ-288) fix: simple key end of range\n* [90f6c3c2](https://github.com/hyperledger/fabric-chaincode-java/commit/90f6c3c2) Update dependencies\n* [526d1cc8](https://github.com/hyperledger/fabric-chaincode-java/commit/526d1cc8) [FABCJ-284](https://jira.hyperledger.org/browse/FABCJ-284) Broken link\n* [7f722053](https://github.com/hyperledger/fabric-chaincode-java/commit/7f722053) force rebuild\n* [9a42effb](https://github.com/hyperledger/fabric-chaincode-java/commit/9a42effb) [FABCJ-285](https://jira.hyperledger.org/browse/FABCJ-285) Remove incorrect log point\n* [c2367768](https://github.com/hyperledger/fabric-chaincode-java/commit/c2367768) Clean up Fabric Version Methodology\n* [88da28f6](https://github.com/hyperledger/fabric-chaincode-java/commit/88da28f6) [FAB-17777](https://jira.hyperledger.org/browse/FAB-17777) Create basic settings.yaml\n* [a6b00f2d](https://github.com/hyperledger/fabric-chaincode-java/commit/a6b00f2d) [FABCJ-283](https://jira.hyperledger.org/browse/FABCJ-283) Update javadoc 2.x link\n* [96fa4d6e](https://github.com/hyperledger/fabric-chaincode-java/commit/96fa4d6e) [FABCJ-283](https://jira.hyperledger.org/browse/FABCJ-283) Update docs to handle new branch\n* [ff031f2d](https://github.com/hyperledger/fabric-chaincode-java/commit/ff031f2d) [FABCJ-283](https://jira.hyperledger.org/browse/FABCJ-283) Bump version number to 3.0.0 - in order to not contradict release-2.x branch\n* [35a5159d](https://github.com/hyperledger/fabric-chaincode-java/commit/35a5159d) [FABCJ-283](https://jira.hyperledger.org/browse/FABCJ-283) Update docker image version to 2.1\n* [67af7977](https://github.com/hyperledger/fabric-chaincode-java/commit/67af7977) [FABCJ-280](https://jira.hyperledger.org/browse/FABCJ-280) Copy chaincode into temporary directory before building\n* [e69168cb](https://github.com/hyperledger/fabric-chaincode-java/commit/e69168cb) [FABCJ-276](https://jira.hyperledger.org/browse/FABCJ-276) Access localmspid\n* [cc673036](https://github.com/hyperledger/fabric-chaincode-java/commit/cc673036) [FABCN-359](https://jira.hyperledger.org/browse/FABCN-359) Ledger Class\n* [f0689360](https://github.com/hyperledger/fabric-chaincode-java/commit/f0689360) [FABCJ-273](https://jira.hyperledger.org/browse/FABCJ-273) Show release-2.0 Javadoc\n* [364cae9d](https://github.com/hyperledger/fabric-chaincode-java/commit/364cae9d) [FABCJ-269](https://jira.hyperledger.org/browse/FABCJ-269) Compatibility Matrix\n* [89ffb592](https://github.com/hyperledger/fabric-chaincode-java/commit/89ffb592) [FABCJ-273](https://jira.hyperledger.org/browse/FABCJ-273) Prepare next release v2.1.0\n* [6c1cdba0](https://github.com/hyperledger/fabric-chaincode-java/commit/6c1cdba0) Java chaincode gRPC server for run external chaincode add NettyGrpcServer with method /Connect for start chat with peer without TLS add example external chaincode\n\n## v2.3.0\nTue  3 Nov 2020 14:20:11 GMT\n\n* [081d5c8](https://github.com/hyperledger/fabric-chaincode-java/commit/081d5c8) Bump version to 2.2.2\n* [b494824](https://github.com/hyperledger/fabric-chaincode-java/commit/b494824) [FABCJ-290](https://jira.hyperledger.org/browse/FABCJ-290) Add release guide\n\n## v2.2.1\nWed  7 Oct 2020 16:21:53 BST\n\n* [cef231c](https://github.com/hyperledger/fabric-chaincode-java/commit/cef231c) [FABCJ-293](https://jira.hyperledger.org/browse/FABCJ-293) Remove gradle from image\n* [d2643ef](https://github.com/hyperledger/fabric-chaincode-java/commit/d2643ef) Minor Performance Improvements\n* [703558c](https://github.com/hyperledger/fabric-chaincode-java/commit/703558c) [FABCJ-291](https://jira.hyperledger.org/browse/FABCJ-291) Startkey needs additional checks For the open ended query, the start and empty keys are empty from the chaincode. However, in the shim, if the start key is an empty key, it is replaced with 0x01  which is nothing but a namespace for the non-composite key.\n* [f35ae08](https://github.com/hyperledger/fabric-chaincode-java/commit/f35ae08) Fix tagging of fabric-javaenv image\n* [cb31d36](https://github.com/hyperledger/fabric-chaincode-java/commit/cb31d36) Bump version to 2.2.1\n\n## v2.2.0\nThu  2 Jul 11:28:13 BST 2020\n\n* [32c8201](https://github.com/hyperledger/fabric-chaincode-java/commit/32c8201) [FABCJ-289](https://jira.hyperledger.org/browse/FABCJ-289) release: 2.2.0 LTS\n* [0948234](https://github.com/hyperledger/fabric-chaincode-java/commit/0948234) [FABCJ-288](https://jira.hyperledger.org/browse/FABCJ-288) fix: simple key end of range\n* [8b06be2](https://github.com/hyperledger/fabric-chaincode-java/commit/8b06be2) [FABCJ-286](https://jira.hyperledger.org/browse/FABCJ-286) Prepare 2.1.2\n\n## v2.1.1\nMon 18 May 09:09:24 BST 2020\n\n* [f0f958e](https://github.com/hyperledger/fabric-chaincode-java/commit/f0f958e) [FABCJ-284](https://jira.hyperledger.org/browse/FABCJ-284) Broken docs link\n* [b89c464](https://github.com/hyperledger/fabric-chaincode-java/commit/b89c464) [FABCJ-285](https://jira.hyperledger.org/browse/FABCJ-285) Remove incorrect log point\n* [93ff6bb](https://github.com/hyperledger/fabric-chaincode-java/commit/93ff6bb) [FABCJ-283](https://jira.hyperledger.org/browse/FABCJ-283) Bump version number to 2.1.1\n\n## v2.1.0\nThu  9 Apr 2020 14:13:36 BST\n\n* [72e6f78](https://github.com/hyperledger/fabric-chaincode-java/commit/72e6f78) [FABCJ-283](https://jira.hyperledger.org/browse/FABCJ-283) Update docker image version\n* [54606f8](https://github.com/hyperledger/fabric-chaincode-java/commit/54606f8) [FABCJ-269](https://jira.hyperledger.org/browse/FABCJ-269) Compatibility Matrix\n\n## v2.0.1\nWed  4 Mar 16:38:58 GMT 2020\n\n* [8cb6a25](https://github.com/hyperledger/fabric-chaincode-java/commit/8cb6a25) [FAB-16136](https://jira.hyperledger.org/browse/FAB-16136) Do not run tests in chaincode container\n* [3710641](https://github.com/hyperledger/fabric-chaincode-java/commit/3710641) [FABCJ-280](https://jira.hyperledger.org/browse/FABCJ-280) Copy chaincode into temporary directory before building\n* [a25a7d6](https://github.com/hyperledger/fabric-chaincode-java/commit/a25a7d6) [FABCJ-276](https://jira.hyperledger.org/browse/FABCJ-276) Access localmspid\n\n## v2.0.0\nFri 24 Jan 10:26:03 GMT 2020\n\n* [659a1c4](https://github.com/hyperledger/fabric-chaincode-java/commit/659a1c4) Port fixes from master branch for Coverage & typos\n* [9cf1e6a](https://github.com/hyperledger/fabric-chaincode-java/commit/9cf1e6a) [FABCI-482](https://jira.hyperledger.org/browse/FABCI-482) Update Nexus URL's to Artifactory\n* [7ab7145](https://github.com/hyperledger/fabric-chaincode-java/commit/7ab7145) Fix typos in README.md\n* [67fdc40](https://github.com/hyperledger/fabric-chaincode-java/commit/67fdc40) [FABCJ-259](https://jira.hyperledger.org/browse/FABCJ-259) Pagination Fix\n* [1609425](https://github.com/hyperledger/fabric-chaincode-java/commit/1609425) Update maintainers list\n* [1a45e3d](https://github.com/hyperledger/fabric-chaincode-java/commit/1a45e3d) [FABCJ-95](https://jira.hyperledger.org/browse/FABCJ-95) Checkstyle\n\n\n## v2.0.0-beta\nThu 12 Dec 12:45:44 GMT 2019\n\n* [4a13009](https://github.com/hyperledger/fabric-chaincode-java/commit/4a13009) Add OWASP dependency checks to build\n* [44c96d7](https://github.com/hyperledger/fabric-chaincode-java/commit/44c96d7) FABCJ-258 Add latest image tag in AZP pipeline\n* [e1d53bf](https://github.com/hyperledger/fabric-chaincode-java/commit/e1d53bf) Remove -SNAPSHOT from package version variable\n* [fedc2ef](https://github.com/hyperledger/fabric-chaincode-java/commit/fedc2ef) Improve integration test reliability\n* [6fd5507](https://github.com/hyperledger/fabric-chaincode-java/commit/6fd5507) [FABCJ-257] Rationalize examples\n* [5d3cd53](https://github.com/hyperledger/fabric-chaincode-java/commit/5d3cd53) [FABCJ-160] Char support\n* [e32e404](https://github.com/hyperledger/fabric-chaincode-java/commit/e32e404) [FABCJ-183] Extra properties appear in JSON from Java Objects\n* [7f3c4e3](https://github.com/hyperledger/fabric-chaincode-java/commit/7f3c4e3) [FAB-17138](https://jira.hyperledger.org/browse/FAB-17138) Publish docker images to nexus\n* [b52d26a](https://github.com/hyperledger/fabric-chaincode-java/commit/b52d26a) [FAB-15634](https://jira.hyperledger.org/browse/FAB-15634) Annotations for Serializer\n* [207bd94](https://github.com/hyperledger/fabric-chaincode-java/commit/207bd94) [FAB-17100](https://jira.hyperledger.org/browse/FAB-17100) Default Thread Pool not set correctly\n* [f50a4ed](https://github.com/hyperledger/fabric-chaincode-java/commit/f50a4ed) [FAB-16712](https://jira.hyperledger.org/browse/FAB-16712) Disable stalebot\n* [ee8a1f4](https://github.com/hyperledger/fabric-chaincode-java/commit/ee8a1f4) Update javadoc location in readme\n* [3951dca](https://github.com/hyperledger/fabric-chaincode-java/commit/3951dca) Fix git user email/name config in azure pipeline\n* [55ad1b9](https://github.com/hyperledger/fabric-chaincode-java/commit/55ad1b9) Update javadoc build to use Hyperledger Bot\n* [4680efc](https://github.com/hyperledger/fabric-chaincode-java/commit/4680efc) Publish javadoc\n* [d4981a3](https://github.com/hyperledger/fabric-chaincode-java/commit/d4981a3) Fix the name of the docker image\n* [6553ffc](https://github.com/hyperledger/fabric-chaincode-java/commit/6553ffc) Update readme\n* [3b029a8](https://github.com/hyperledger/fabric-chaincode-java/commit/3b029a8) Fix the name of the docker image\n* [d01eeff](https://github.com/hyperledger/fabric-chaincode-java/commit/d01eeff) Add artifacts to build result\n* [3c2c27c](https://github.com/hyperledger/fabric-chaincode-java/commit/3c2c27c) [FAB-16712](https://jira.hyperledger.org/browse/FAB-16712) Update contributing guide\n* [d13e0c0](https://github.com/hyperledger/fabric-chaincode-java/commit/d13e0c0) Next steps in publishing\n* [75a0bed](https://github.com/hyperledger/fabric-chaincode-java/commit/75a0bed) Next steps in publishing\n* [fd2e21a](https://github.com/hyperledger/fabric-chaincode-java/commit/fd2e21a) Next steps in publishing\n* [5618de6](https://github.com/hyperledger/fabric-chaincode-java/commit/5618de6) Push the snapshot docker images to nexus\n* [5a11c6e](https://github.com/hyperledger/fabric-chaincode-java/commit/5a11c6e) Push the snapshot docker images to nexus\n* [4eff463](https://github.com/hyperledger/fabric-chaincode-java/commit/4eff463) [FAB-16315](https://jira.hyperledger.org/browse/FAB-16315) Improved Load Ability\n* [11a26ce](https://github.com/hyperledger/fabric-chaincode-java/commit/11a26ce) Fix Azure Pipelines\n* [7b3e509](https://github.com/hyperledger/fabric-chaincode-java/commit/7b3e509) [FAB-16711](https://jira.hyperledger.org/browse/FAB-16711) Azure pipelines\n* [a3304ec](https://github.com/hyperledger/fabric-chaincode-java/commit/a3304ec) [FAB-16707](https://jira.hyperledger.org/browse/FAB-16707) Remove Gradle warnings\n* [af3dec0](https://github.com/hyperledger/fabric-chaincode-java/commit/af3dec0) [IN-68] Add default GitHub SECURITY policy\n* [88b9397](https://github.com/hyperledger/fabric-chaincode-java/commit/88b9397) [FAB-16680](https://jira.hyperledger.org/browse/FAB-16680) Fix cloudflare error on jitpack.io\n* [f6076eb](https://github.com/hyperledger/fabric-chaincode-java/commit/f6076eb) [FAB-16669](https://jira.hyperledger.org/browse/FAB-16669) WIP: Use native Java 11 ALPN support\n* [5520053](https://github.com/hyperledger/fabric-chaincode-java/commit/5520053) [FAB-16669](https://jira.hyperledger.org/browse/FAB-16669) Update gRPC and Protocol Buffers code\n* [abff28f](https://github.com/hyperledger/fabric-chaincode-java/commit/abff28f) [FAB-16655](https://jira.hyperledger.org/browse/FAB-16655) Warnings as errors for Java chaincode docs\n* [50e75bf](https://github.com/hyperledger/fabric-chaincode-java/commit/50e75bf) [FAB-16655](https://jira.hyperledger.org/browse/FAB-16655) Warnings as errors for Java chaincode\n* [d79f5a6](https://github.com/hyperledger/fabric-chaincode-java/commit/d79f5a6) [FAB-6415](https://jira.hyperledger.org/browse/FAB-6415) Remove tests from Docker image build\n* [35d5884](https://github.com/hyperledger/fabric-chaincode-java/commit/35d5884) [FAB-6415](https://jira.hyperledger.org/browse/FAB-6415) Various chaincode deployment updates\n* [12b5243](https://github.com/hyperledger/fabric-chaincode-java/commit/12b5243) [FAB-16493](https://jira.hyperledger.org/browse/FAB-16493) Fixed gradle build on windows\n* [2f6be19](https://github.com/hyperledger/fabric-chaincode-java/commit/2f6be19) [FAB-6415](https://jira.hyperledger.org/browse/FAB-6415) Remove cglib dependency\n* [56c533e](https://github.com/hyperledger/fabric-chaincode-java/commit/56c533e) [FAB-6415](https://jira.hyperledger.org/browse/FAB-6415) Upgrade Docker image to Java 11\n* [5dbbea7](https://github.com/hyperledger/fabric-chaincode-java/commit/5dbbea7) [FAB-6415](https://jira.hyperledger.org/browse/FAB-6415) Replace org.reflections with classgraph\n* [059d043](https://github.com/hyperledger/fabric-chaincode-java/commit/059d043) [FAB-6415](https://jira.hyperledger.org/browse/FAB-6415) Add javax.xml.bind dependency for Java 11\n* [cbe663b](https://github.com/hyperledger/fabric-chaincode-java/commit/cbe663b) [FAB-6415](https://jira.hyperledger.org/browse/FAB-6415) Upgrade to Gradle 5.6.2 and Maven 3.6.2\n* [887153c](https://github.com/hyperledger/fabric-chaincode-java/commit/887153c) [FAB-6415](https://jira.hyperledger.org/browse/FAB-6415) Add javax.annotation dependency for Java 11\n* [66e9079](https://github.com/hyperledger/fabric-chaincode-java/commit/66e9079) [FAB-16489](https://jira.hyperledger.org/browse/FAB-16489) Add CODEOWNERS\n* [182c050](https://github.com/hyperledger/fabric-chaincode-java/commit/182c050) [FAB-15507](https://jira.hyperledger.org/browse/FAB-15507) Add doc\n* [1a38b84](https://github.com/hyperledger/fabric-chaincode-java/commit/1a38b84) [FABN-1320] Remove sed from git_tag.sh script\n* [25ed6c1](https://github.com/hyperledger/fabric-chaincode-java/commit/25ed6c1) [FABN-1320] Fix git_tag.sh\n* [f47f601](https://github.com/hyperledger/fabric-chaincode-java/commit/f47f601) [FAB-15929](https://jira.hyperledger.org/browse/FAB-15929) Add getPrivateDataHash support\n* [4371d07](https://github.com/hyperledger/fabric-chaincode-java/commit/4371d07) [FAB-16217](https://jira.hyperledger.org/browse/FAB-16217) Do not load JSON Schema schema from network\n* [44d76f4](https://github.com/hyperledger/fabric-chaincode-java/commit/44d76f4) [FAB-15895](https://jira.hyperledger.org/browse/FAB-15895) Added client identity to context\n* [9169e14](https://github.com/hyperledger/fabric-chaincode-java/commit/9169e14) New maintainer application\n* [12309b5](https://github.com/hyperledger/fabric-chaincode-java/commit/12309b5) [FAB-16091](https://jira.hyperledger.org/browse/FAB-16091) Handle invalid contract name\n* [e8ca970](https://github.com/hyperledger/fabric-chaincode-java/commit/e8ca970) [FAB-15647](https://jira.hyperledger.org/browse/FAB-15647) Fix markup of README\n* [360d75a](https://github.com/hyperledger/fabric-chaincode-java/commit/360d75a) [FAB-15883](https://jira.hyperledger.org/browse/FAB-15883) Removed swagger annotations\n* [25c5be6](https://github.com/hyperledger/fabric-chaincode-java/commit/25c5be6) [FAB-15615](https://jira.hyperledger.org/browse/FAB-15615) Add ChaincodeException support\n* [9077581](https://github.com/hyperledger/fabric-chaincode-java/commit/9077581) [FAB-15823](https://jira.hyperledger.org/browse/FAB-15823) Fix getStringPayload npe\n* [e163d3f](https://github.com/hyperledger/fabric-chaincode-java/commit/e163d3f) [FAB-15743](https://jira.hyperledger.org/browse/FAB-15743) Align Context\n* [5ad6ed8](https://github.com/hyperledger/fabric-chaincode-java/commit/5ad6ed8) [FAB-15507](https://jira.hyperledger.org/browse/FAB-15507) Exclude unnecessary contract javadoc\n* [9cc6553](https://github.com/hyperledger/fabric-chaincode-java/commit/9cc6553) [FAB-15720](https://jira.hyperledger.org/browse/FAB-15720) prevent duplicate transactions\n* [f87de8e](https://github.com/hyperledger/fabric-chaincode-java/commit/f87de8e) [FAB-15632](https://jira.hyperledger.org/browse/FAB-15632) Add name element to transaction annotation\n* [d726175](https://github.com/hyperledger/fabric-chaincode-java/commit/d726175) [FAB-13803](https://jira.hyperledger.org/browse/FAB-13803) Parameter Marshalling\n* [72dc716](https://github.com/hyperledger/fabric-chaincode-java/commit/72dc716) [FAB-15214](https://jira.hyperledger.org/browse/FAB-15214) Remove init annotation\n* [509bfbf](https://github.com/hyperledger/fabric-chaincode-java/commit/509bfbf) [FAB-13802](https://jira.hyperledger.org/browse/FAB-13802) Metadata Support\n* [0467032](https://github.com/hyperledger/fabric-chaincode-java/commit/0467032) Application to be consider for maintainer of this repo\n* [526f36d](https://github.com/hyperledger/fabric-chaincode-java/commit/526f36d) [FAB-13802](https://jira.hyperledger.org/browse/FAB-13802) Return types update\n* [1662390](https://github.com/hyperledger/fabric-chaincode-java/commit/1662390) [FAB-13912](https://jira.hyperledger.org/browse/FAB-13912) Implement new interfaces\n* [bd1c269](https://github.com/hyperledger/fabric-chaincode-java/commit/bd1c269) [FAB-14961](https://jira.hyperledger.org/browse/FAB-14961) Update to the FAQ\n* [dc02c3b](https://github.com/hyperledger/fabric-chaincode-java/commit/dc02c3b) [FAB-14995](https://jira.hyperledger.org/browse/FAB-14995) Prepare for next release \n\n## v2.0.0-alpha\nSun Apr  9 15:37:09 IDT 2019\n\n* [b62740c](https://github.com/hyperledger/fabric-chaincode-java/commit/b62740c) [FAB-13798](https://jira.hyperledger.org/browse/FAB-13798) New interfaces\n* [8235149](https://github.com/hyperledger/fabric-chaincode-java/commit/8235149) [FAB-13795](https://jira.hyperledger.org/browse/FAB-13795) Contract definition\n* [762a955](https://github.com/hyperledger/fabric-chaincode-java/commit/762a955) [FAB-13800](https://jira.hyperledger.org/browse/FAB-13800) Transaction Context\n* [351acb5](https://github.com/hyperledger/fabric-chaincode-java/commit/351acb5) [FAB-13794](https://jira.hyperledger.org/browse/FAB-13794) New Annotations\n* [3e13a57](https://github.com/hyperledger/fabric-chaincode-java/commit/3e13a57) [FAB-12960](https://jira.hyperledger.org/browse/FAB-12960) Adding cc without main method\n* [40bf2c1](https://github.com/hyperledger/fabric-chaincode-java/commit/40bf2c1) [FAB-14533](https://jira.hyperledger.org/browse/FAB-14533) Updating integration tests\n* [b17d8a2](https://github.com/hyperledger/fabric-chaincode-java/commit/b17d8a2) [FAB-12504](https://jira.hyperledger.org/browse/FAB-12504) Added maven integration test.\n* [0e76b72](https://github.com/hyperledger/fabric-chaincode-java/commit/0e76b72) [FAB-14522](https://jira.hyperledger.org/browse/FAB-14522) README update: sdk compatibility\n* [e5d3e40](https://github.com/hyperledger/fabric-chaincode-java/commit/e5d3e40) [FAB-14460](https://jira.hyperledger.org/browse/FAB-14460) Better chaincode source check\n* [0adaf35](https://github.com/hyperledger/fabric-chaincode-java/commit/0adaf35) [FAB-13490](https://jira.hyperledger.org/browse/FAB-13490) javaenv image based on openjdk:slim-8\n* [e33b4bd](https://github.com/hyperledger/fabric-chaincode-java/commit/e33b4bd) [FAB-13672](https://jira.hyperledger.org/browse/FAB-13672) stop using deprecated left closure\n* [c3e342a](https://github.com/hyperledger/fabric-chaincode-java/commit/c3e342a) [FAB-13097](https://jira.hyperledger.org/browse/FAB-13097) Getting correct jar\n* [cc76d2f](https://github.com/hyperledger/fabric-chaincode-java/commit/cc76d2f) [FAB-13097](https://jira.hyperledger.org/browse/FAB-13097) Adding shim 1.3.0 to docker image\n* [b22858b](https://github.com/hyperledger/fabric-chaincode-java/commit/b22858b) Configure Stale ProBot\n* [1279d2c](https://github.com/hyperledger/fabric-chaincode-java/commit/1279d2c) [FAB-13436](https://jira.hyperledger.org/browse/FAB-13436) multistage docker build\n* [035a7d2](https://github.com/hyperledger/fabric-chaincode-java/commit/035a7d2) [FAB-13243](https://jira.hyperledger.org/browse/FAB-13243) fix javaenv docker build tag\n* [ad89bbb](https://github.com/hyperledger/fabric-chaincode-java/commit/ad89bbb) [FAB-13248](https://jira.hyperledger.org/browse/FAB-13248) Update dependencies for sonatype\n* [cea4db0](https://github.com/hyperledger/fabric-chaincode-java/commit/cea4db0) [FAB-13229](https://jira.hyperledger.org/browse/FAB-13229) Prepare for next release (2.0.0 on master)\n* [4c6cd6c](https://github.com/hyperledger/fabric-chaincode-java/commit/4c6cd6c) [FAB-13236](https://jira.hyperledger.org/browse/FAB-13236) Publish jars to sonatype\n\n## v1.4.0-rc1\nSun Apr  7 15:37:00 IDT 2019\n\n* [2d26e5d](https://github.com/hyperledger/fabric-chaincode-java/commit/2d26e5d) [FAB-13117](https://jira.hyperledger.org/browse/FAB-13117) Release java chaincode 1.4.0-rc1\n* [3628832](https://github.com/hyperledger/fabric-chaincode-java/commit/3628832) [FAB-13194](https://jira.hyperledger.org/browse/FAB-13194) Script to publish javaenv multiarch image\n* [455100c](https://github.com/hyperledger/fabric-chaincode-java/commit/455100c) [FAB-12426](https://jira.hyperledger.org/browse/FAB-12426) Fix java chaincode return status.\n* [ea26118](https://github.com/hyperledger/fabric-chaincode-java/commit/ea26118) [FAB-12197](https://jira.hyperledger.org/browse/FAB-12197) Integration tests\n* [3b61085](https://github.com/hyperledger/fabric-chaincode-java/commit/3b61085) [FAB-12110](https://jira.hyperledger.org/browse/FAB-12110) SimpleAsset java chaincode example\n* [b46fc70](https://github.com/hyperledger/fabric-chaincode-java/commit/b46fc70) [FAB-12328](https://jira.hyperledger.org/browse/FAB-12328) java cc pagination\n* [68685dc](https://github.com/hyperledger/fabric-chaincode-java/commit/68685dc) [FAB-12469](https://jira.hyperledger.org/browse/FAB-12469) Java sbe tests\n* [748ea9f](https://github.com/hyperledger/fabric-chaincode-java/commit/748ea9f) [FAB-12468](https://jira.hyperledger.org/browse/FAB-12468) Utility classes for java sbe\n* [b4b3a87](https://github.com/hyperledger/fabric-chaincode-java/commit/b4b3a87) [FAB-12467](https://jira.hyperledger.org/browse/FAB-12467) State-based endorsement\n* [c32c4c4](https://github.com/hyperledger/fabric-chaincode-java/commit/c32c4c4) [FAB-12568](https://jira.hyperledger.org/browse/FAB-12568) Adding identities to JavaCC\n* [fb81132](https://github.com/hyperledger/fabric-chaincode-java/commit/fb81132) Fix LFID for gennadyl\n* [7522309](https://github.com/hyperledger/fabric-chaincode-java/commit/7522309) Retire dormant maintainers, suggest new nomination\n* [321db66](https://github.com/hyperledger/fabric-chaincode-java/commit/321db66) [FAB-12444](https://jira.hyperledger.org/browse/FAB-12444) Update java cc to baseimage 0.4.14\n* [aa177d2](https://github.com/hyperledger/fabric-chaincode-java/commit/aa177d2) [FAB-12347](https://jira.hyperledger.org/browse/FAB-12347) Update java cc to baseimage 0.4.13\n* [e9c5602](https://github.com/hyperledger/fabric-chaincode-java/commit/e9c5602) [FAB-12223](https://jira.hyperledger.org/browse/FAB-12223) Adding FAQ file\n* [af01201](https://github.com/hyperledger/fabric-chaincode-java/commit/af01201) [FAB-12278](https://jira.hyperledger.org/browse/FAB-12278) Fixing java cc build script\n* [52cc6bd](https://github.com/hyperledger/fabric-chaincode-java/commit/52cc6bd) [FAB-12157](https://jira.hyperledger.org/browse/FAB-12157) Hadling chaincode in default package\n* [8dcd819](https://github.com/hyperledger/fabric-chaincode-java/commit/8dcd819) [FAB-12152](https://jira.hyperledger.org/browse/FAB-12152) Prepare for next release (1.4.0 on master)\n* [cc91af5](https://github.com/hyperledger/fabric-chaincode-java/commit/cc91af5) [FAB-12152](https://jira.hyperledger.org/browse/FAB-12152) Prepare for next release (1.3.0 on master)\n* [9cbb36c](https://github.com/hyperledger/fabric-chaincode-java/commit/9cbb36c) [FAB-10525](https://jira.hyperledger.org/browse/FAB-10525) Fix the bug getStateByPartialCompositeKey\n\n## v1.3.0-rc1\nTue Sep 25 15:25:05 EDT 2018\n\n* [224bc4d](https://github.com/hyperledger/fabric-chaincode-java/commit/224bc4d) [FAB-12160](https://jira.hyperledger.org/browse/FAB-12160) Release fabric-chaincode-java v1.3.0-rc1\n* [333d91b](https://github.com/hyperledger/fabric-chaincode-java/commit/333d91b) [FAB-12129](https://jira.hyperledger.org/browse/FAB-12129) Update baseimage version\n* [01dd207](https://github.com/hyperledger/fabric-chaincode-java/commit/01dd207) [FAB-12115](https://jira.hyperledger.org/browse/FAB-12115) Fix groupId in shim jars\n* [5d7ed1c](https://github.com/hyperledger/fabric-chaincode-java/commit/5d7ed1c) [FAB-9519](https://jira.hyperledger.org/browse/FAB-9519) Java shim readmy and tutorial\n* [44a1367](https://github.com/hyperledger/fabric-chaincode-java/commit/44a1367) [FAB-12017](https://jira.hyperledger.org/browse/FAB-12017) Adding java docs\n* [56e2a11](https://github.com/hyperledger/fabric-chaincode-java/commit/56e2a11) [FAB-11839](https://jira.hyperledger.org/browse/FAB-11839) Adding FVT tests\n* [ac70a6f](https://github.com/hyperledger/fabric-chaincode-java/commit/ac70a6f) [FAB-10032](https://jira.hyperledger.org/browse/FAB-10032) Adding unit test\n* [ac6c906](https://github.com/hyperledger/fabric-chaincode-java/commit/ac6c906) [FAB-11750](https://jira.hyperledger.org/browse/FAB-11750) Updating version to 1.3.0\n* [e80ba7c](https://github.com/hyperledger/fabric-chaincode-java/commit/e80ba7c) [FAB-11288](https://jira.hyperledger.org/browse/FAB-11288) Adding private data functions\n* [79497bc](https://github.com/hyperledger/fabric-chaincode-java/commit/79497bc) [FAB-11741](https://jira.hyperledger.org/browse/FAB-11741) Reformat code\n* [71ca2a2](https://github.com/hyperledger/fabric-chaincode-java/commit/71ca2a2) [FAB-11664](https://jira.hyperledger.org/browse/FAB-11664) Enable separate docker build\n* [52f2c8b](https://github.com/hyperledger/fabric-chaincode-java/commit/52f2c8b) [FAB-11485](https://jira.hyperledger.org/browse/FAB-11485) Fixing empty proposal handling\n* [2b35a46](https://github.com/hyperledger/fabric-chaincode-java/commit/2b35a46) [FAB-11304](https://jira.hyperledger.org/browse/FAB-11304) Handling READY message from peer\n* [4b27549](https://github.com/hyperledger/fabric-chaincode-java/commit/4b27549) [FAB-9380](https://jira.hyperledger.org/browse/FAB-9380) remove FSM from java chaincode shim\n* [f5e6fb4](https://github.com/hyperledger/fabric-chaincode-java/commit/f5e6fb4) [FAB-9920](https://jira.hyperledger.org/browse/FAB-9920) Java shim mutual TLS\n* [d295c96](https://github.com/hyperledger/fabric-chaincode-java/commit/d295c96) [FAB-9424](https://jira.hyperledger.org/browse/FAB-9424) Adding docker build support\n* [1cb0493](https://github.com/hyperledger/fabric-chaincode-java/commit/1cb0493) [FAB-10845](https://jira.hyperledger.org/browse/FAB-10845) Remove protos files\n* [6c8abf4](https://github.com/hyperledger/fabric-chaincode-java/commit/6c8abf4) [FAB-9416](https://jira.hyperledger.org/browse/FAB-9416): Add gradle task to update protos\n* [e3be99e](https://github.com/hyperledger/fabric-chaincode-java/commit/e3be99e) [FAB-9407](https://jira.hyperledger.org/browse/FAB-9407): Extract JavaCC shim protos\n* [e4c9867](https://github.com/hyperledger/fabric-chaincode-java/commit/e4c9867) [FAB-9359](https://jira.hyperledger.org/browse/FAB-9359) add CODE_OF_CONDUCT.md and other docs\n* [8772201](https://github.com/hyperledger/fabric-chaincode-java/commit/8772201) [FAB-9063](https://jira.hyperledger.org/browse/FAB-9063) Provide link to Fabric committers\n* [4a9406b](https://github.com/hyperledger/fabric-chaincode-java/commit/4a9406b) Add Maintainers to fabric-chaincode-java\n* [091a081](https://github.com/hyperledger/fabric-chaincode-java/commit/091a081) [FAB-8986](https://jira.hyperledger.org/browse/FAB-8986): Harden gradle build configuration\n* [bb958eb](https://github.com/hyperledger/fabric-chaincode-java/commit/bb958eb) [FAB-8346](https://jira.hyperledger.org/browse/FAB-8346) sync chaincode proto files w/ fabric\n* [c399853](https://github.com/hyperledger/fabric-chaincode-java/commit/c399853) [FAB-7989](https://jira.hyperledger.org/browse/FAB-7989) --peerAddress should be --peer.address\n* [308eb63](https://github.com/hyperledger/fabric-chaincode-java/commit/308eb63) [FAB-7626](https://jira.hyperledger.org/browse/FAB-7626) Move to Gradle 4.4.1\n* [d73edd6](https://github.com/hyperledger/fabric-chaincode-java/commit/d73edd6) [FAB-7294](https://jira.hyperledger.org/browse/FAB-7294) enable shim jar publication\n* [d9c463e](https://github.com/hyperledger/fabric-chaincode-java/commit/d9c463e) [FAB-7091](https://jira.hyperledger.org/browse/FAB-7091) Extract StreamObserver out of ChaincodeBase\n* [e3644f4](https://github.com/hyperledger/fabric-chaincode-java/commit/e3644f4) [FAB-6889](https://jira.hyperledger.org/browse/FAB-6889) add channel ID to chaincode message\n* [2eda08b](https://github.com/hyperledger/fabric-chaincode-java/commit/2eda08b) [FAB-6726](https://jira.hyperledger.org/browse/FAB-6726) move to gradle 4.2.1\n* [5cf4f73](https://github.com/hyperledger/fabric-chaincode-java/commit/5cf4f73) [FAB-3650](https://jira.hyperledger.org/browse/FAB-3650) add getBinding() API\n* [a3b7d71](https://github.com/hyperledger/fabric-chaincode-java/commit/a3b7d71) [FAB-3649](https://jira.hyperledger.org/browse/FAB-3649) add getTransient() API\n* [3cb86b0](https://github.com/hyperledger/fabric-chaincode-java/commit/3cb86b0) [FAB-3648](https://jira.hyperledger.org/browse/FAB-3648) add getCreator() API\n* [5982e40](https://github.com/hyperledger/fabric-chaincode-java/commit/5982e40) [FAB-3653](https://jira.hyperledger.org/browse/FAB-3653) add getTxTimestamp() API\n* [5566a62](https://github.com/hyperledger/fabric-chaincode-java/commit/5566a62) [FAB-6681](https://jira.hyperledger.org/browse/FAB-6681) Add code coverage report and verification\n* [64de43a](https://github.com/hyperledger/fabric-chaincode-java/commit/64de43a) [FAB-6637](https://jira.hyperledger.org/browse/FAB-6637) add license check to fabric-chaincode-java\n* [9f2f4f9](https://github.com/hyperledger/fabric-chaincode-java/commit/9f2f4f9) [FAB-3470](https://jira.hyperledger.org/browse/FAB-3470) update composite key format\n* [61b8fc2](https://github.com/hyperledger/fabric-chaincode-java/commit/61b8fc2) [FAB-3651](https://jira.hyperledger.org/browse/FAB-3651) add getSignedProposal() API\n* [8c2352a](https://github.com/hyperledger/fabric-chaincode-java/commit/8c2352a) [FAB-6494](https://jira.hyperledger.org/browse/FAB-6494) Add unit tests for ChaincodeStubImpl\n* [b58bcc2](https://github.com/hyperledger/fabric-chaincode-java/commit/b58bcc2) Update Jim's RC ID in MAINTAINERS.rst\n* [02520ac](https://github.com/hyperledger/fabric-chaincode-java/commit/02520ac) Initial MAINTAINERS file\n* [915824f](https://github.com/hyperledger/fabric-chaincode-java/commit/915824f) [FAB-6435](https://jira.hyperledger.org/browse/FAB-6435) Copy Java shim from fabric repository\n* [067b712](https://github.com/hyperledger/fabric-chaincode-java/commit/067b712) [FAB-5928](https://jira.hyperledger.org/browse/FAB-5928) Initial gradle build script\n\n\n\n"
  },
  {
    "path": "CODEOWNERS",
    "content": "# SPDX-License-Identifier: Apache-2.0\n\n# Fabric Chaincode Java Maintainers\n*\t@hyperledger/fabric-chaincode-java-maintainers\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "Code of Conduct Guidelines\n==========================\n\nPlease review the Hyperledger [Code of\nConduct](https://wiki.hyperledger.org/community/hyperledger-project-code-of-conduct)\nbefore participating. It is important that we keep things civil.\n\n<a rel=\"license\" href=\"http://creativecommons.org/licenses/by/4.0/\"><img alt=\"Creative Commons License\" style=\"border-width:0\" src=\"https://i.creativecommons.org/l/by/4.0/88x31.png\" /></a><br />This work is licensed under a <a rel=\"license\" href=\"http://creativecommons.org/licenses/by/4.0/\">Creative Commons Attribution 4.0 International License</a>.\n"
  },
  {
    "path": "COMPATIBILITY.md",
    "content": "# Support and Compatibility\n\nGithub is used for code base management and issue tracking.\n\n## Summary of Compatibility\n\nThis table shows the summary of the compatibility of the Java chaincode libraries, together with the JVM version they require.\n\n| Java chaincode version | Minimum supported Java | Java runtime | Docker image platforms |\n|------------------------|------------------------|--------------|------------------------|\n| v1.4                   | 8                      | 8            | amd64                  |\n| v2.2                   | 11                     | 11           | amd64                  |\n| v2.5.0 - v2.5.4        | 11                     | 11           | amd64, arm64           |\n| v2.5.5 - v2.5.7        | 11                     | 21           | amd64, arm64           |\n| v2.5.8+                | 11                     | 25           | amd64, arm64           |\n\nThe Java runtime provided by the chaincode Docker image determines the maximum Java version (and features) that smart contract code can exploit when using the default Java chaincode container.\n\nSubject to a suitable runtime environment, the Java chaincode libraries can be used to communicate with Fabric peers at different LTS versions. The level of functionality is determined by the Fabric version in use and channel capabilities.\n\nAll Docker images, chaincode libraries and tools are tested using amd64 (x86-64) only.\n\n## Chaincode builder\n\nThe default Fabric chaincode builder creates a Docker container to run deployed smart contracts. Java chaincode Docker containers are built using the `hyperledger/fabric-javaenv` Docker image, tagged with the same major and minor version as the Fabric peer version. For example, Fabric v2.5 creates Java chaincode containers using the `hyperledger/fabric-javaenv:2.5` Docker image. Fabric v3 continues to use the v2.5 Java chaincode image.\n\nA different chaincode Docker image can be specified using the `CORE_CHAINCODE_JAVA_RUNTIME` environment variable on the Fabric peer. For example, `CORE_CHAINCODE_JAVA_RUNTIME=example/customJavaRuntime:latest`.\n\nWith Fabric v2 and later, an alternative chaincode builder can be configured on the Fabric peer. In this case the configured chaincode builder controls how chaincode is launched. See the [Fabric documentation](https://hyperledger-fabric.readthedocs.io/en/release-2.5/cc_launcher.html) for further details.\n\n## Chaincode packaging\n\nWhen using the `hyperledger/fabric-javaenv` Java chaincode Docker images, deployed chaincode is built as follows:\n\n- If both Gradle and Maven files are present, Gradle is used.\n- Gradle build files can be either Groovy or Kotlin.\n- If Gradle or Maven wrappers are present, they will be used instead of the preinstalled Gradle or Maven versions.\n\nRemember that when using the wrappers, code will be downloaded from the Internet. Keep this in mind for any installation with limited network access.\n\nAlternatively, it is recommended to package prebuilt JAR files, including the smart contract and all dependencies. In this case, no Internet access is required when deploying Java chaincode.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to fabric-chaincode-java\n\nWe welcome contributions to the [Hyperledger Fabric](https://hyperledger-fabric.readthedocs.io) Project. There's always plenty to do!\n\nIf you have any questions about the project or how to contribute, you can find us in the [fabric-contracts-api](https://discordapp.com/channels/905194001349627914/943090527920877598) channel on [Discord](https://discord.lfdecentralizedtrust.org/).\n\nHere are a few guidelines to help you contribute successfully...\n\n## Issues\n\nAll issues are tracked in the issues tab in GitHub. If you find a bug which we don't already know about, you can help us by creating a new issue describing the problem. Please include as much detail as possible to help us track down the cause.If you want to begin contributing code, looking through our open issues is a good way to start. Try looking for recent issues with detailed descriptions first, or ask us on Discord if you're unsure which issue to choose.\n\n## Enhancements\n\nMake sure you have the support of the Hyperledger Fabric community before investing a lot of effort in project enhancements. Please look up the [Fabric RFC](https://github.com/hyperledger/fabric-rfcs) process for large changes.\n\n## Pull Requests\n\nWe use our own forks and [Github Flow](https://docs.github.com/en/get-started/using-github/github-flow) to deliver changes to the code. Follow these steps to deliver your first pull request:\n\n1. [Fork the repository](https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project) and create a new branch from `main`.\n2. If you've added code that should be tested, add tests!\n3. If you've added any new features or made breaking changes, update the documentation.\n4. Ensure all the tests pass.\n5. Include the JIRA issue number, a descriptive message, and the [Developer Certificate of Origin (DCO) sign-off](https://github.com/dcoapp/app#how-it-works) on all commit messages.\n6. [Issue a pull request](https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project#making-a-pull-request)!\n7. [GitHub Actions](https://github.com/hyperledger/fabric-chaincode-java/actions) builds must succeed before the pull request can be reviewed and merged.\n\n## Coding Style\n\nPlease to try to be consistent with the rest of the code and conform to checkstyle rules where they are provided. [Spotless](https://github.com/diffplug/spotless) is used to enforce code formatting. You can run `./gradlew spotlessApply` to apply the mandated code formatting to the codebase before submitting changes to avoid failing the build with formatting violations.\n\n## Code of Conduct Guidelines <a name=\"conduct\"></a>\n\nSee our [Code of Conduct Guidelines](../blob/main/CODE_OF_CONDUCT.md).\n\n## Maintainers <a name=\"maintainers\"></a>\n\nShould you have any questions or concerns, please reach out to one of the project's [Maintainers](../blob/main/MAINTAINERS.md).\n\n\n## How to work with the Codebase\n\nSome useful gradle commands to help with building.  You can add or remove the `--no-daemon` as you wish; depending on the performance of you local machine.\n\n```shell\n# build everything\n./gradlew --no-daemon build\n\n# clean up to force tests and compile to rerun\n./gradlew clean cleanTest\n./gradlew --no-daemon :fabric-chaincode-shim:build\n\n# build docker image\n./gradlew :fabric-chaincode-docker:buildImage\n```\n\nYou can also scan for vulnerabilities in dependencies (requires [Make](https://www.gnu.org/software/make/) and [Go](https://go.dev/) to be installed):\n```shell\nmake scan\n```\n\n## Hyperledger Fabric\n\nSee the\n[Hyperledger Fabric contributors guide](http://hyperledger-fabric.readthedocs.io/en/latest/CONTRIBUTING.html) for more details, including other Hyperledger Fabric projects you may wish to contribute to.\n\n---\n\n[![Creative Commons License](https://i.creativecommons.org/l/by/4.0/88x31.png)](http://creativecommons.org/licenses/by/4.0/)  \nThis work is licensed under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/)\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright {yyyy} {name of copyright owner}\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\n"
  },
  {
    "path": "MAINTAINERS.md",
    "content": "# Maintainers\n\n| Name         | GitHub                                                | Chat            | email                      |\n| ------------ | ----------------------------------------------------- | --------------- | -------------------------- |\n| Dave Enyeart | [denyeart](https://github.com/denyeart)               | denyeart        | <enyeart@us.ibm.com>       |\n| Mark Lewis   | [bestbeforetoday](https://github.com/bestbeforetoday) | bestbeforetoday | <Mark.S.Lewis@outlook.com> |\n\n# Retired Maintainers\n\n| Name                    | GitHub                                                  | Chat          | email                                 |\n| ----------------------- | ------------------------------------------------------- | ------------- | ------------------------------------- |\n| Artem Barger            | [c0rwin](https://github.com/c0rwin)                     | c0rwin        | <bartem@il.ibm.com>                   |\n| Matthew B White         | [mbwhite](https://github.com/mbwhite)                   | mbwhite       | <whitemat@uk.ibm.com>                 |\n| James Taylor            | [jt-nti](https://github.com/jt-nti)                     | jtonline      | <jamest@uk.ibm.com>                   |\n| Gari Singh              | [mastersingh24](https://github.com/mastersingh24)       | mastersingh24 | <gari.r.singh@gmail.com>              |\n| Gennady Laventman       | [gennadylaventman](https://github.com/gennadylaventman) | gennadyl      | <gennady@il.ibm.com>                  |\n| Jim Zhang               | [jimthematrix](https://github.com/jimthematrix)         | jimthematrix  | <jim\\_the\\_matrix@hotmail.com>        |\n| Luis Sanchez            | [sanchezl](https://github.com/sanchezl)                 | sanchezl      | <sanchezl@us.ibm.com>                 |\n| Srinivasan Muralidharan | [muralisrini](https://github.com/muralisrini)           | muralisr      | <srinivasan.muralidharan99@gmail.com> |\n| Yacov Manevich          | [yacovm](https://github.com/yacovm)                     | yacovm        | <yacovm@il.ibm.com>                   |\n\nAlso: Please see the [Release Manager section](https://github.com/hyperledger/fabric/blob/main/MAINTAINERS.md)\n\n<a rel=\"license\" href=\"http://creativecommons.org/licenses/by/4.0/\"><img alt=\"Creative Commons License\" style=\"border-width:0\" src=\"https://i.creativecommons.org/l/by/4.0/88x31.png\" /></a><br />This work is licensed under a <a rel=\"license\" href=\"http://creativecommons.org/licenses/by/4.0/\">Creative Commons Attribution 4.0 International License</a>.\n"
  },
  {
    "path": "Makefile",
    "content": "#\r\n# SPDX-License-Identifier: Apache-2.0\r\n#\r\n\r\nbin_dir := bin\r\nosv-scanner := $(bin_dir)/osv-scanner\r\n\r\nkernel_name := $(shell uname -s | tr '[:upper:]' '[:lower:]')\r\nmachine_hardware := $(shell uname -m)\r\nifeq ($(machine_hardware), x86_64)\r\n\tmachine_hardware := amd64\r\nendif\r\nifeq ($(machine_hardware), aarch64)\r\n\tmachine_hardware := arm64\r\nendif\r\n\r\n.PHONY: scan\r\nscan: $(osv-scanner)\r\n\trm -f fabric-chaincode-shim/gradle.lockfile\r\n\t./gradlew --quiet :fabric-chaincode-shim:dependencies --write-locks --configuration runtimeClasspath\r\n\tbin/osv-scanner scan --lockfile=fabric-chaincode-shim/gradle.lockfile\r\n\r\n.PHONY: scan-all\r\nscan-all: $(osv-scanner)\r\n\trm -f fabric-chaincode-shim/gradle.lockfile\r\n\t./gradlew --quiet :fabric-chaincode-shim:dependencies --write-locks\r\n\tbin/osv-scanner scan --lockfile=fabric-chaincode-shim/gradle.lockfile\r\n\r\n\r\n.PHONY: install-osv-scanner\r\ninstall-osv-scanner:\r\n\tmkdir -p '$(bin_dir)'\r\n\tcurl --fail --location --show-error --silent --output '$(osv-scanner)' \\\r\n    \t\t'https://github.com/google/osv-scanner/releases/latest/download/osv-scanner_$(kernel_name)_$(machine_hardware)'\r\n\tchmod u+x '$(osv-scanner)'\r\n\r\n$(osv-scanner):\r\n\t$(MAKE) install-osv-scanner\r\n"
  },
  {
    "path": "README.md",
    "content": "# Hyperledger Fabric Chaincode Java\n\n[![Build Status](https://dev.azure.com/Hyperledger/Fabric-Chaincode-Java/_apis/build/status/Fabric-Chaincode-Java?branchName=main)](https://dev.azure.com/Hyperledger/Fabric-Chaincode-Java/_build/latest?definitionId=39&branchName=main)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.hyperledger.fabric-chaincode-java/fabric-chaincode-shim/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.hyperledger.fabric-chaincode-java/fabric-chaincode-shim)\n[![Discord](https://img.shields.io/discord/905194001349627914?label=discord)](https://discordapp.com/channels/905194001349627914/943090527920877598)\n\nThis is a Java based implementation of Hyperledger Fabric chaincode shim APIs, which enables development of smart contracts using the Java language.\n\nThis project creates `fabric-chaincode-shim` jar\nfiles for developers' consumption and the `hyperledger/fabric-javaenv` docker image\nto run Java chaincode.\n\n## Getting Started\n\nApplication developers interested in developing Java smart contracts for Hyperledger Fabric should read the [JavaDoc](https://hyperledger.github.io/fabric-chaincode-java/) which includes download information, and links to documentation and samples.\n\n## Project structure\n\n### fabric-chaincode-shim\n\nContains the java shim classes that define Java chaincode API and way to communicate with Fabric peers.\n\n### fabric-chaincode-docker\n\nContains instructions to build the `hyperledger/fabric-javaenv` docker image.\n\n### fabric-chaincode-integration-test\n\nContains higher level tests for Java chaincode.\n\n> **Note:** in the future these should be replaced with a separate suite of [Cucumber](https://cucumber.io) tests which run against all chaincode implementations.\n\n### examples\n\nThe following technical examples are in this repository. Please see the tutorials in the [documentation](https://hyperledger-fabric.readthedocs.io/en/latest/tutorials.html)\n\n\n- **fabric-contract-example-gradle**  -  Contains an example Java contract built using gradle\n- **fabric-contract-example-maven**  -  Contains an example Java contract built using maven\n- **fabric-contract-example-gradle-kotlin**  -  Contains an example Kotlin contract build using gradle (Kotlin gradle files)\n- **fabric-chaincode-example-sacc**  -  Contains an example java chaincode gradle project that includes sample chaincode and basic gradle build instructions.\n- **fabric-chaincode-example-sbe**  -  Contains an example java chaincode gradle project that includes state based endorsement\n\n## 'dev' main branch builds\n\nThese 'dev' drivers are built from the main branch only, and have a version format including the date for example `2.3.1.dev.20210303`.\nThey are published to Artifactory. These can be accessed via the repository at\n```\n    maven {\n        url \"https://hyperledger.jfrog.io/hyperledger/fabric-maven\"\n    }\n```\n\nThey can be accessed in a build file like this\n\n```\ndependencies {\n    compile group: 'org.hyperledger.fabric-chaincode-java', name: 'fabric-chaincode-shim', version: '2.3.1.dev.+'\n }\n```\n\n\n## Building and testing\n\nMake sure you have the following prereqs installed:\n\n- [Docker](https://www.docker.com/get-docker)\n- [Docker Compose](https://docs.docker.com/compose/install/)\n- [JDK 11](https://adoptium.net/)\n\n> **Note:** Java can be installed using [sdkman](https://sdkman.io/).\n\nClone the repository if you haven't already.\n\n```\ngit clone https://github.com/hyperledger/fabric-chaincode-java.git\n```\n\nBuild java shim jars (proto and shim jars) and install them to local maven repository.\n\n```\ncd fabric-chaincode-java\n./gradlew clean build install\n```\n\n> **Note:** `./gradlew clean build classes` can be used instead to reduce the binaries that are built. This should be sufficient for using the local repository.\n\nBuild javaenv docker image, to have it locally.\n\n```\n./gradlew buildImage\n```\n\n## Compatibility\n\nFor details on what Java runtime and versions of Hyperledger Fabric can be used please see the [compatibility document](COMPATIBILITY.md).\n\n---\n\n[![Creative Commons License](https://i.creativecommons.org/l/by/4.0/88x31.png)](http://creativecommons.org/licenses/by/4.0/)  \nThis work is licensed under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/)\n"
  },
  {
    "path": "RELEASING.md",
    "content": "# Releasing\n\nThe following artifacts are created as a result of releasing Fabric Chaincode Java:\n\n- `fabric-javaenv` Docker images:\n  - [Docker Hub](https://hub.docker.com/r/hyperledger/fabric-javaenv)\n  - [GitHub Packages](https://github.com/orgs/hyperledger/packages/container/package/fabric-javaenv)\n- `fabric-chaincode-shim` Java libraries:\n  - [Maven Central](https://central.sonatype.com/artifact/org.hyperledger.fabric-chaincode-java/fabric-chaincode-shim)\n  - [GitHub Packages](https://github.com/hyperledger/fabric-chaincode-java/packages/50049)\n\n## Before releasing\n\nThe following tasks are required before releasing:\n\n- Ensure the version number in `build.gradle` is the required release version.\n- Check the last branch build passed since exactly this repository state will be released.\n\n## Create release\n\nCreating a GitHub release on the [releases page](https://github.com/hyperledger/fabric-chaincode-java/releases) will trigger the build to publish the new release.\n\nWhen drafting the release, create a new tag for the new version (with a `v` prefix). For example: `v2.1.4`\n\nSee previous releases for examples of the title and description.\n\n## After releasing\n\n- Update the version number in `build.gradle` to the next version.\n- Update image version numbers in `fabric-chaincode-docker/build.gradle` to match the next version.\n- Update the `fabric-chaincode-shim` dependency version in all `build.gradle` and `pom.xml` files within `fabric-chaincode-integration-test/src/contracts` to match the next version.\n- Update the `fabric-chaincode-shim` dependency version in all `build.gradle`, `build.gradle.kts` and `pom.xml` files within `examples` to match the last _released_ version.\n- Check that `COMPATIBILITY.md` is correct and update if required.\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Hyperledger Security Policy\n\n## Reporting a Security Bug\n\nIf you think you have discovered a security issue in any of the Hyperledger projects, we'd love to hear from you. We will take all security bugs seriously and if confirmed upon investigation we will patch it within a reasonable amount of time and release a public security bulletin discussing the impact and credit the discoverer.\n\nThere are two ways to report a security bug. The easiest is to email a description of the flaw and any related information (e.g. reproduction steps, version) to [security at hyperledger dot org](mailto:security@hyperledger.org).\n\nThe other way is to file a confidential security bug in our [JIRA bug tracking system](https://jira.hyperledger.org). Be sure to set the “Security Level” to “Security issue”.\n\nThe process by which the Hyperledger Security Team handles security bugs is documented further in our [Defect Response page](https://wiki.hyperledger.org/display/SEC/Defect+Response) on our [wiki](https://wiki.hyperledger.org).\n\n"
  },
  {
    "path": "build.gradle",
    "content": "/*\n * Copyright IBM Corp. 2018 All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\nplugins {\n    id \"com.github.ben-manes.versions\" version \"0.54.0\"\n    id \"com.diffplug.spotless\" version \"8.4.0\"\n    id \"com.gradleup.nmcp.aggregation\" version \"1.4.4\"\n    id \"com.gradleup.nmcp\" version \"1.4.4\" apply false\n}\n\nversion = '2.5.9'\n\n// If the nightly property is set, then this is the scheduled main\n// build - and we should publish this to artifactory\n//\n// Use the .dev.<number> format to match Maven convention\nif (properties.containsKey('NIGHTLY')) {\n    version = version + '.dev.' + getDate()\n    ext.nightly = true   // set property for use in subprojects\n} else {\n    ext.nightly = false\n}\n\nnmcpAggregation {\n    centralPortal {\n        username = findProperty('mavenCentralUsername')\n        password = findProperty('mavenCentralPassword')\n        publishingType = \"AUTOMATIC\"\n    }\n}\n\ndependencies {\n    nmcpAggregation(project(':fabric-chaincode-shim'))\n}\n\nallprojects {\n    apply plugin: \"com.diffplug.spotless\"\n\n    repositories {\n        mavenCentral()\n    }\n\n    spotless {\n        format 'misc', {\n            target '*.gradle', '.gitattributes', '.gitignore'\n            trimTrailingWhitespace()\n            leadingTabsToSpaces()\n            endWithNewline()\n        }\n    }\n}\n\nsubprojects {\n    apply plugin: 'java'\n    apply plugin: \"maven-publish\"\n\n    group = 'org.hyperledger.fabric-chaincode-java'\n    version = rootProject.version\n\n    compileJava {\n        options.release = 11\n        options.compilerArgs += ['-Werror', '-Xlint:all']\n    }\n\n    dependencies {\n        implementation 'commons-cli:commons-cli:1.11.0'\n        implementation 'commons-logging:commons-logging:1.3.6'\n\n        testImplementation platform('org.junit:junit-bom:6.0.3')\n        testImplementation 'org.junit.jupiter:junit-jupiter'\n        testRuntimeOnly 'org.junit.platform:junit-platform-launcher'\n        testImplementation 'org.assertj:assertj-core:3.27.7'\n        testImplementation 'org.mockito:mockito-core:5.23.0'\n        testImplementation 'uk.org.webcompere:system-stubs-jupiter:2.1.8'\n\n        testImplementation 'org.hamcrest:hamcrest-library:3.0'\n    }\n\n    test {\n        useJUnitPlatform()\n    }\n\n    spotless {\n        java {\n            removeUnusedImports()\n            palantirJavaFormat().formatJavadoc(true)\n            formatAnnotations()\n        }\n    }\n}\n\n// Get the date in the reverse format for sorting\nstatic def getDate() {\n    def date = new Date()\n    def formattedDate = date.format('yyyyMMdd')\n    return formattedDate\n}\n"
  },
  {
    "path": "docs/404.md",
    "content": "---\ntitle: \"404 - Page Not Found\"\npermalink: /404.html\n---\n\n## The page you wanted does not exist\n\nIf you were looking for Javadoc, try one of the releases below:\n\n{% include javadocs.html %}\n"
  },
  {
    "path": "docs/_config.yml",
    "content": "theme: minima\ntitle: \"fabric-chaincode-java\"\nreleases:\n  - main\n  - release-1.4\n  - release-2.2\n"
  },
  {
    "path": "docs/_includes/footer.html",
    "content": ""
  },
  {
    "path": "docs/_includes/header.html",
    "content": "<header class=\"site-header\">\n\n  <div class=\"wrapper\">\n    <a class=\"site-title\" rel=\"author\" href=\"{{ \"/\" | relative_url }}\">{{ site.title | escape }}</a>\n\n    <nav class=\"site-nav\">\n      <input type=\"checkbox\" id=\"nav-trigger\" class=\"nav-trigger\" />\n      <label for=\"nav-trigger\">\n        <span class=\"menu-icon\">\n          <svg viewBox=\"0 0 18 15\" width=\"18px\" height=\"15px\">\n            <path d=\"M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z\"/>\n          </svg>\n        </span>\n      </label>\n\n      <div class=\"trigger\">\n        <a class=\"page-link\" href=\"https://github.com/hyperledger/fabric-chaincode-java/\">View on GitHub</a>\n      </div>\n    </nav>\n  </div>\n</header>\n"
  },
  {
    "path": "docs/_includes/javadocs.html",
    "content": "<ul>\n  {%- for release in site.releases -%}\n    <li><a class=\"page-link\" href=\"{{ release | relative_url }}/api/\">{{ release | escape }}</a></li>\n  {%- endfor -%}\n</ul>\n"
  },
  {
    "path": "docs/index.md",
    "content": "---\nlayout: home\n---\n\nHyperledger Fabric offers a number of SDKs to support developing smart contracts (chaincode)\nin various programming languages. There are two other smart contract SDKs available for Go, and Node.js, in addition to this Java SDK:\n\n  * [Go SDK documentation](https://godoc.org/github.com/hyperledger/fabric/core/chaincode/shim)\n  * [Node.js SDK documentation](https://hyperledger.github.io/fabric-chaincode-node/)\n\n## Documentation\n\nDetailed explanation on the concepts and programming model for smart contracts can be found in the [Chaincode Tutorials section of the Hyperledger Fabric documentation](https://hyperledger-fabric.readthedocs.io/en/latest/developapps/smartcontract.html#).\n\nJavadoc is available for each release:\n\n{% include javadocs.html %}\n\n## Download\n\nGradle:\n\n```\ndependencies {\n  implementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:VERSION'\n}\n```\n\nMaven:\n\n```\n<dependency>\n  <groupId>org.hyperledger.fabric-chaincode-java</groupId>\n  <artifactId>fabric-chaincode-shim</artifactId>\n  <version>VERSION</version>\n</dependency>\n```\n\nMore options can be found on the [central maven repository](https://search.maven.org/artifact/org.hyperledger.fabric-chaincode-java/fabric-chaincode-shim/).\n\nCheck the [release notes](https://github.com/hyperledger/fabric-chaincode-java/releases) for the changes in each version.\n\n## Compatibility\n\nFor details on what versions of Java and Hyperledger Fabric can be used please see the [compatibility document](https://github.com/hyperledger/fabric-chaincode-java/blob/main/COMPATIBILITY.md).\n\n## Samples\n\nSeveral Java chaincode samples can be found in the [fabric-samples repository](https://github.com/hyperledger/fabric-samples)\n"
  },
  {
    "path": "examples/fabric-contract-example-as-service/Dockerfile",
    "content": "# Copyright 2019 IBM All Rights Reserved.\n# SPDX-License-Identifier: Apache-2.0\n\n# Example multi-stage dockerfile for Java Chaincode\n\n# the first stage \nFROM gradle:9-jdk21 AS gradle_build\n \n# copy the build.gradle and src code to the container\nCOPY src/ src/\nCOPY build.gradle ./ \n\n# Build and package our code\nRUN gradle build shadowJar\n\n\n# the second stage of our build just needs the compiled files\nFROM eclipse-temurin:25-jre\n# copy only the artifacts we need from the first stage and discard the rest\nCOPY --from=gradle_build /home/gradle/build/libs/chaincode.jar /chaincode.jar\n \nENV PORT=9999\nEXPOSE 9999\n\n# set the startup command to execute the jar\nCMD [\"java\", \"-jar\", \"/chaincode.jar\"]"
  },
  {
    "path": "examples/fabric-contract-example-as-service/README.md",
    "content": "# Java Chaincode -as-a-service\n\nThis example shows how to start the chaincode in it's 'as-a-service' mode.\nNote that this has been improved over the original mechanism\n\n## Build Changes\n\nThere are no changes required to tbe build file. For example the `build.gradle` can be left like this\n\n```\n    manifest {\n        attributes 'Main-Class': 'org.hyperledger.fabric.contract.ContractRouter'\n    }\n```\n\n## Contract Code\n\nNo changes are required to the contract code. Note that the previous 'bootstrap' main method is not required.\n\n## Environment Variables\n\nThe setting of the `CHAINCODE_SERVER_ADDRESS` environment variable will trigger the code to work in the 'as-a-service' mode.  This should be set to the hostname:port that the server will be exposed on.  Typically this would be\n\n```\nCHAINCODE_SERVER_ADDRESS=0.0.0.0:9999\n```\n\n*NOTE* if `CHAINCODE_SERVER_ADDRESS` is set, and the chaincode is deployed as a regular chaincode, this will result in a failure. The chaincode will still start in 'as-a-service' mode.\n\nThe `CORE_CHAINCODE_ID_NAME` must also be set to match the ID used when deploying the chaincode.\n\n*For TLS* ensure that \n- `CORE_PEERT_TLS_ENABLED` is true\n- `CORE_PEER_TLS_ROOTCERT_FILE` is set to the certificate of the root CA\n- `CORE_TLS_CLIENT_KEY_FILE` and `CORE_TLS_CLIENT_CERT_FILE` if using mutual TLS (PEM encoded)\n\n\n## Dockerfile\n\nThere is an example dockerfile that shows how the chaincode can be built into a container image.\n"
  },
  {
    "path": "examples/fabric-contract-example-as-service/build.gradle",
    "content": "plugins {\n    id 'com.gradleup.shadow' version '9.3.1'\n    id 'java'\n}\n\nversion = '0.0.1'\n\nrepositories {\n    mavenCentral()\n    maven {\n        url = \"https://www.jitpack.io\"\n    }\n}\n\ndependencies {\n    implementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:2.5.8'\n    implementation 'org.json:json:20251224'\n    testImplementation platform('org.junit:junit-bom:6.0.2')\n    testImplementation 'org.junit.jupiter:junit-jupiter'\n    testImplementation 'org.assertj:assertj-core:3.27.7'\n    testImplementation 'org.mockito:mockito-core:5.21.0'\n    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'\n}\n\nshadowJar {\n    archiveBaseName = 'chaincode'\n    archiveVersion = ''\n    archiveClassifier = ''\n    duplicatesStrategy = DuplicatesStrategy.INCLUDE\n    mergeServiceFiles()\n\n    manifest {\n        attributes 'Main-Class': 'org.example.Application'\n    }\n}\n\ncompileJava {\n    options.release.set(11)\n    options.compilerArgs << \"-Xlint:unchecked\" << \"-Xlint:deprecation\" << \"-parameters\"\n}\n\ntest {\n    useJUnitPlatform()\n    testLogging {\n        events \"PASSED\", \"SKIPPED\", \"FAILED\"\n    }\n}\n"
  },
  {
    "path": "examples/fabric-contract-example-as-service/src/main/java/org/example/contract/MyAsset.java",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.example.contract;\n\nimport org.hyperledger.fabric.contract.annotation.DataType;\nimport org.hyperledger.fabric.contract.annotation.Property;\nimport org.json.JSONObject;\n\n@DataType()\npublic class MyAsset {\n\n    @Property()\n    private String value;\n\n    public MyAsset() {\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public void setValue(String value) {\n        this.value = value;\n    }\n\n    public String toJSONString() {\n        return new JSONObject(this).toString();\n    }\n\n    public static MyAsset fromJSONString(String json) {\n        String value = new JSONObject(json).getString(\"value\");\n        MyAsset asset = new MyAsset();\n        asset.setValue(value);\n        return asset;\n    }\n}\n"
  },
  {
    "path": "examples/fabric-contract-example-as-service/src/main/java/org/example/contract/MyAssetContract.java",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.example.contract;\n\nimport static java.nio.charset.StandardCharsets.UTF_8;\n\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.Default;\nimport org.hyperledger.fabric.contract.annotation.Transaction;\n\n@Contract\n@Default\npublic class MyAssetContract implements ContractInterface {\n\n    public MyAssetContract() {\n\n    }\n\n    @Transaction()\n    public boolean myAssetExists(Context ctx, String myAssetId) {\n        byte[] buffer = ctx.getStub().getState(myAssetId);\n        return (buffer != null && buffer.length > 0);\n    }\n\n    @Transaction()\n    public void createMyAsset(Context ctx, String myAssetId, String value) {\n        boolean exists = myAssetExists(ctx, myAssetId);\n        if (exists) {\n            throw new RuntimeException(\"The asset \" + myAssetId + \" already exists\");\n        }\n        MyAsset asset = new MyAsset();\n        asset.setValue(value);\n        ctx.getStub().putState(myAssetId, asset.toJSONString().getBytes(UTF_8));\n    }\n\n    @Transaction()\n    public MyAsset readMyAsset(Context ctx, String myAssetId) {\n        boolean exists = myAssetExists(ctx, myAssetId);\n        if (!exists) {\n            throw new RuntimeException(\"The asset \" + myAssetId + \" does not exist\");\n        }\n\n        MyAsset newAsset = MyAsset.fromJSONString(new String(ctx.getStub().getState(myAssetId), UTF_8));\n        return newAsset;\n    }\n\n    @Transaction()\n    public void updateMyAsset(Context ctx, String myAssetId, String newValue) {\n        boolean exists = myAssetExists(ctx, myAssetId);\n        if (!exists) {\n            throw new RuntimeException(\"The asset \" + myAssetId + \" does not exist\");\n        }\n        MyAsset asset = new MyAsset();\n        asset.setValue(newValue);\n\n        ctx.getStub().putState(myAssetId, asset.toJSONString().getBytes(UTF_8));\n    }\n\n    @Transaction()\n    public void deleteMyAsset(Context ctx, String myAssetId) {\n        boolean exists = myAssetExists(ctx, myAssetId);\n        if (!exists) {\n            throw new RuntimeException(\"The asset \" + myAssetId + \" does not exist\");\n        }\n        ctx.getStub().delState(myAssetId);\n    }\n\n}"
  },
  {
    "path": "examples/fabric-contract-example-as-service/src/test/java/org/example/MyAssetContractTest.java",
    "content": "/*\n * SPDX-License-Identifier: Apache License 2.0\n */\n\npackage org.example;\n\nimport static java.nio.charset.StandardCharsets.UTF_8;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\nimport java.nio.charset.StandardCharsets;\nimport org.example.contract.MyAsset;\nimport org.example.contract.MyAssetContract;\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.shim.ChaincodeServerProperties;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\n\n\npublic final class MyAssetContractTest {\n\n    @Nested\n    class AssetExists {\n\n        @Test\n        public void noProperAsset() {\n\n            MyAssetContract contract = new MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            when(stub.getState(\"10001\")).thenReturn(new byte[]{});\n            boolean result = contract.myAssetExists(ctx, \"10001\");\n\n            assertFalse(result);\n        }\n\n        @Test\n        public void assetExists() {\n\n            MyAssetContract contract = new MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            when(stub.getState(\"10001\")).thenReturn(new byte[]{42});\n            boolean result = contract.myAssetExists(ctx, \"10001\");\n\n            assertTrue(result);\n\n        }\n\n        @Test\n        public void noKey() {\n            MyAssetContract contract = new MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            when(stub.getState(\"10002\")).thenReturn(null);\n            boolean result = contract.myAssetExists(ctx, \"10002\");\n\n            assertFalse(result);\n\n        }\n\n    }\n\n    @Nested\n    class AssetCreates {\n\n        @Test\n        public void newAssetCreate() {\n            MyAssetContract contract = new MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            String json = \"{\\\"value\\\":\\\"TheAsset\\\"}\";\n\n            contract.createMyAsset(ctx, \"10001\", \"TheAsset\");\n\n            verify(stub).putState(\"10001\", json.getBytes(UTF_8));\n        }\n\n        @Test\n        public void alreadyExists() {\n            MyAssetContract contract = new MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            when(stub.getState(\"10002\")).thenReturn(new byte[]{42});\n\n            Exception thrown = assertThrows(RuntimeException.class, () -> {\n                contract.createMyAsset(ctx, \"10002\", \"TheAsset\");\n            });\n\n            assertEquals(thrown.getMessage(), \"The asset 10002 already exists\");\n\n        }\n\n    }\n\n    @Test\n    public void assetRead() {\n        MyAssetContract contract = new MyAssetContract();\n        Context ctx = mock(Context.class);\n        ChaincodeStub stub = mock(ChaincodeStub.class);\n        when(ctx.getStub()).thenReturn(stub);\n\n        MyAsset asset = new MyAsset();\n        asset.setValue(\"Valuable\");\n\n        String json = asset.toJSONString();\n        when(stub.getState(\"10001\")).thenReturn(json.getBytes(StandardCharsets.UTF_8));\n\n        MyAsset returnedAsset = contract.readMyAsset(ctx, \"10001\");\n        assertEquals(returnedAsset.getValue(), asset.getValue());\n    }\n\n    @Nested\n    class AssetUpdates {\n\n        @Test\n        public void updateExisting() {\n            MyAssetContract contract = new MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n            when(stub.getState(\"10001\")).thenReturn(new byte[]{42});\n\n            contract.updateMyAsset(ctx, \"10001\", \"updates\");\n\n            String json = \"{\\\"value\\\":\\\"updates\\\"}\";\n            verify(stub).putState(\"10001\", json.getBytes(UTF_8));\n        }\n\n        @Test\n        public void updateMissing() {\n            MyAssetContract contract = new MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            when(stub.getState(\"10001\")).thenReturn(null);\n\n            Exception thrown = assertThrows(RuntimeException.class, () -> {\n                contract.updateMyAsset(ctx, \"10001\", \"TheAsset\");\n            });\n\n            assertEquals(thrown.getMessage(), \"The asset 10001 does not exist\");\n        }\n\n    }\n\n    @Test\n    public void assetDelete() {\n        MyAssetContract contract = new MyAssetContract();\n        Context ctx = mock(Context.class);\n        ChaincodeStub stub = mock(ChaincodeStub.class);\n        when(ctx.getStub()).thenReturn(stub);\n        when(stub.getState(\"10001\")).thenReturn(null);\n\n        Exception thrown = assertThrows(RuntimeException.class, () -> {\n            contract.deleteMyAsset(ctx, \"10001\");\n        });\n\n        assertEquals(thrown.getMessage(), \"The asset 10001 does not exist\");\n    }\n\n    @Test\n    public void test() {\n        ChaincodeServerProperties chaincodeServerProperties = new ChaincodeServerProperties();\n        chaincodeServerProperties.setKeepAliveTimeMinutes(-10);\n\n        assertEquals(true, true);\n    }\n\n}"
  },
  {
    "path": "examples/fabric-contract-example-gradle/.gitignore",
    "content": ".gradle/\nbuild/\nbin/"
  },
  {
    "path": "examples/fabric-contract-example-gradle/README.md",
    "content": "This example needs to use gradle4.6  please install this first\n\neg using sdkman\n\n`sdk install gradle 4.6`\n\n\nand then add the wrapper code before building\n\n`gradle wrapper`"
  },
  {
    "path": "examples/fabric-contract-example-gradle/build.gradle",
    "content": "plugins {\n    id 'com.gradleup.shadow' version '9.3.1'\n    id 'java'\n}\n\nversion = '0.0.1'\n\nrepositories {\n    mavenCentral()\n    maven {\n        url = \"https://www.jitpack.io\"\n    }\n}\n\ndependencies {\n    implementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:2.5.8'\n    implementation 'org.json:json:20251224'\n    testImplementation platform('org.junit:junit-bom:6.0.2')\n    testImplementation 'org.junit.jupiter:junit-jupiter'\n    testImplementation 'org.assertj:assertj-core:3.27.7'\n    testImplementation 'org.mockito:mockito-core:5.21.0'\n    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'\n}\n\nshadowJar {\n    archiveBaseName = 'chaincode'\n    archiveVersion = ''\n    archiveClassifier = ''\n    duplicatesStrategy = DuplicatesStrategy.INCLUDE\n    mergeServiceFiles()\n\n    manifest {\n        attributes 'Main-Class': 'org.hyperledger.fabric.contract.ContractRouter'\n    }\n}\n\ncompileJava {\n    options.release.set(11)\n    options.compilerArgs << \"-Xlint:unchecked\" << \"-Xlint:deprecation\" << \"-parameters\"\n}\n\ntest {\n    useJUnitPlatform()\n    testLogging {\n        events \"PASSED\", \"SKIPPED\", \"FAILED\"\n    }\n}\n"
  },
  {
    "path": "examples/fabric-contract-example-gradle/src/main/java/org/example/MyAsset.java",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.example;\n\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.DataType;\nimport org.hyperledger.fabric.contract.annotation.Property;\nimport org.json.JSONObject;\n\n@DataType()\npublic class MyAsset {\n\n    @Property()\n    private String value;\n\n    public MyAsset(){\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public void setValue(String value) {\n        this.value = value;\n    }\n\n    public String toJSONString() {\n        return new JSONObject(this).toString();\n    }\n\n    public static MyAsset fromJSONString(String json) {\n        String value = new JSONObject(json).getString(\"value\");\n        MyAsset asset = new MyAsset();\n        asset.setValue(value);\n        return asset;\n    }\n}\n"
  },
  {
    "path": "examples/fabric-contract-example-gradle/src/main/java/org/example/MyAssetContract.java",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.example;\n\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.Default;\nimport org.hyperledger.fabric.contract.annotation.Transaction;\n\nimport io.swagger.v3.oas.annotations.info.Contact;\nimport io.swagger.v3.oas.annotations.info.Info;\nimport io.swagger.v3.oas.annotations.info.License;\nimport static java.nio.charset.StandardCharsets.UTF_8;\n\n@Contract(name = \"MyAssetContract\",\n    info = @Info(title = \"MyAsset contract\",\n                description = \"Very basic Java Contract example\",\n                version = \"0.0.1\",\n                license =\n                        @License(name = \"SPDX-License-Identifier: Apache-2.0\",\n                                url = \"\"),\n                                contact =  @Contact(email = \"MyAssetContract@example.com\",\n                                                name = \"MyAssetContract\",\n                                                url = \"http://MyAssetContract.me\")))\n@Default\npublic class MyAssetContract implements ContractInterface {\n    public  MyAssetContract() {\n\n    }\n    @Transaction()\n    public boolean myAssetExists(Context ctx, String myAssetId) {\n        byte[] buffer = ctx.getStub().getState(myAssetId);\n        return (buffer != null && buffer.length > 0);\n    }\n\n    @Transaction()\n    public void createMyAsset(Context ctx, String myAssetId, String value) {\n        boolean exists = myAssetExists(ctx,myAssetId);\n        if (exists) {\n            throw new RuntimeException(\"The asset \"+myAssetId+\" already exists\");\n        }\n        MyAsset asset = new MyAsset();\n        asset.setValue(value);\n        ctx.getStub().putState(myAssetId, asset.toJSONString().getBytes(UTF_8));\n    }\n\n    @Transaction()\n    public MyAsset readMyAsset(Context ctx, String myAssetId) {\n        boolean exists = myAssetExists(ctx,myAssetId);\n        if (!exists) {\n            throw new RuntimeException(\"The asset \"+myAssetId+\" does not exist\");\n        }\n\n        MyAsset newAsset = MyAsset.fromJSONString(new String(ctx.getStub().getState(myAssetId),UTF_8));\n        return newAsset;\n    }\n\n    @Transaction()\n    public void updateMyAsset(Context ctx, String myAssetId, String newValue) {\n        boolean exists = myAssetExists(ctx,myAssetId);\n        if (!exists) {\n            throw new RuntimeException(\"The asset \"+myAssetId+\" does not exist\");\n        }\n        MyAsset asset = new MyAsset();\n        asset.setValue(newValue);\n\n        ctx.getStub().putState(myAssetId, asset.toJSONString().getBytes(UTF_8));\n    }\n\n    @Transaction()\n    public void deleteMyAsset(Context ctx, String myAssetId) {\n        boolean exists = myAssetExists(ctx,myAssetId);\n        if (!exists) {\n            throw new RuntimeException(\"The asset \"+myAssetId+\" does not exist\");\n        }\n        ctx.getStub().delState(myAssetId);\n    }\n\n}"
  },
  {
    "path": "examples/fabric-contract-example-gradle/src/test/java/org/example/MyAssetContractTest.java",
    "content": "/*\n * SPDX-License-Identifier: Apache License 2.0\n */\n\npackage org.example;\nimport static java.nio.charset.StandardCharsets.UTF_8;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\nimport java.nio.charset.StandardCharsets;\n\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\n\n\npublic final class MyAssetContractTest {\n\n    @Nested\n    class AssetExists {\n        @Test\n        public void noProperAsset() {\n\n            MyAssetContract contract = new  MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            when(stub.getState(\"10001\")).thenReturn(new byte[] {});\n            boolean result = contract.myAssetExists(ctx,\"10001\");\n\n            assertFalse(result);\n        }\n\n        @Test\n        public void assetExists() {\n\n            MyAssetContract contract = new  MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            when(stub.getState(\"10001\")).thenReturn(new byte[] {42});\n            boolean result = contract.myAssetExists(ctx,\"10001\");\n\n            assertTrue(result);\n\n        }\n\n        @Test\n        public void noKey() {\n            MyAssetContract contract = new  MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            when(stub.getState(\"10002\")).thenReturn(null);\n            boolean result = contract.myAssetExists(ctx,\"10002\");\n\n            assertFalse(result);\n\n        }\n\n    }\n\n    @Nested\n    class AssetCreates {\n\n        @Test\n        public void newAssetCreate() {\n            MyAssetContract contract = new  MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            String json = \"{\\\"value\\\":\\\"TheAsset\\\"}\";\n\n            contract.createMyAsset(ctx, \"10001\", \"TheAsset\");\n\n            verify(stub).putState(\"10001\", json.getBytes(UTF_8));\n        }\n\n        @Test\n        public void alreadyExists() {\n            MyAssetContract contract = new  MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            when(stub.getState(\"10002\")).thenReturn(new byte[] { 42 });\n\n            Exception thrown = assertThrows(RuntimeException.class, () -> {\n                contract.createMyAsset(ctx, \"10002\", \"TheAsset\");\n            });\n\n            assertEquals(thrown.getMessage(), \"The asset 10002 already exists\");\n\n        }\n\n    }\n\n    @Test\n    public void assetRead() {\n        MyAssetContract contract = new  MyAssetContract();\n        Context ctx = mock(Context.class);\n        ChaincodeStub stub = mock(ChaincodeStub.class);\n        when(ctx.getStub()).thenReturn(stub);\n\n        MyAsset asset = new  MyAsset();\n        asset.setValue(\"Valuable\");\n\n        String json = asset.toJSONString();\n        when(stub.getState(\"10001\")).thenReturn(json.getBytes(StandardCharsets.UTF_8));\n\n        MyAsset returnedAsset = contract.readMyAsset(ctx, \"10001\");\n        assertEquals(returnedAsset.getValue(), asset.getValue());\n    }\n\n    @Nested\n    class AssetUpdates {\n        @Test\n        public void updateExisting() {\n            MyAssetContract contract = new  MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n            when(stub.getState(\"10001\")).thenReturn(new byte[] { 42 });\n\n            contract.updateMyAsset(ctx, \"10001\", \"updates\");\n\n            String json = \"{\\\"value\\\":\\\"updates\\\"}\";\n            verify(stub).putState(\"10001\", json.getBytes(UTF_8));\n        }\n\n        @Test\n        public void updateMissing() {\n            MyAssetContract contract = new  MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            when(stub.getState(\"10001\")).thenReturn(null);\n\n            Exception thrown = assertThrows(RuntimeException.class, () -> {\n                contract.updateMyAsset(ctx, \"10001\", \"TheAsset\");\n            });\n\n            assertEquals(thrown.getMessage(), \"The asset 10001 does not exist\");\n        }\n\n    }\n\n    @Test\n    public void assetDelete() {\n        MyAssetContract contract = new  MyAssetContract();\n        Context ctx = mock(Context.class);\n        ChaincodeStub stub = mock(ChaincodeStub.class);\n        when(ctx.getStub()).thenReturn(stub);\n        when(stub.getState(\"10001\")).thenReturn(null);\n\n        Exception thrown = assertThrows(RuntimeException.class, () -> {\n            contract.deleteMyAsset(ctx, \"10001\");\n        });\n\n        assertEquals(thrown.getMessage(), \"The asset 10001 does not exist\");\n    }\n\n}"
  },
  {
    "path": "examples/fabric-contract-example-gradle-kotlin/.fabricignore",
    "content": "#\n# SPDX-License-Identifier: Apache-2.0\n#\n\n/.classpath\n/.git/\n/.gradle/\n/.project\n/.settings/\n/bin/\n/build/\n"
  },
  {
    "path": "examples/fabric-contract-example-gradle-kotlin/.gitignore",
    "content": "#\n# SPDX-License-Identifier: Apache-2.0\n#\n\n/.classpath\n/.gradle/\n/.project\n/.settings/\n/bin/\n/build/\n"
  },
  {
    "path": "examples/fabric-contract-example-gradle-kotlin/build.gradle.kts",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\nimport com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar\n\n\nplugins {\n    id(\"com.gradleup.shadow\") version \"9.3.1\"\n    id(\"org.jetbrains.kotlin.jvm\") version \"2.2.21\"\n}\n\n\n\nversion = \"0.0.1\"\n\ndependencies {\n    implementation(\"org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:2.5.8\")\n    implementation(\"org.json:json:20250517\")\n    implementation(\"org.jetbrains.kotlin:kotlin-stdlib-jdk8\")\n           \n    testImplementation(\"org.junit.jupiter:junit-jupiter:6.0.1\")\n    testImplementation(\"com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0\")\n}\n\nrepositories {\n    mavenCentral()\n    maven {\n        setUrl(\"https://jitpack.io\")\n    }\n}\n\ntasks {\n    \"shadowJar\"(ShadowJar::class) {\n        archiveBaseName = \"chaincode\"\n        archiveVersion = \"\"\n        archiveClassifier = \"\"\n        duplicatesStrategy = DuplicatesStrategy.INCLUDE\n        mergeServiceFiles()\n        manifest {\n            attributes(mapOf(\"Main-Class\" to \"org.hyperledger.fabric.contract.ContractRouter\"))\n        }\n    }\n}\n\n\ntasks.withType<Test> {\n    useJUnitPlatform()\n    testLogging {\n        events(\"passed\", \"skipped\", \"failed\")\n    }\n}\n"
  },
  {
    "path": "examples/fabric-contract-example-gradle-kotlin/gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.6-bin.zip\nnetworkTimeout=10000\nvalidateDistributionUrl=true\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "examples/fabric-contract-example-gradle-kotlin/gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\n# This is normally unused\n# shellcheck disable=SC2034\nAPP_BASE_NAME=${0##*/}\n# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)\nAPP_HOME=$( cd \"${APP_HOME:-./}\" > /dev/null && pwd -P ) || exit\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    if ! command -v java >/dev/null 2>&1\n    then\n        die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Collect all arguments for the java command:\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,\n#     and any embedded shellness will be escaped.\n#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be\n#     treated as '${Hostname}' itself on the command line.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "examples/fabric-contract-example-gradle-kotlin/gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\"==\"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\r\n@rem This is normally unused\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif %ERRORLEVEL% equ 0 goto execute\r\n\r\necho. 1>&2\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2\r\necho. 1>&2\r\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\r\necho location of your Java installation. 1>&2\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho. 1>&2\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2\r\necho. 1>&2\r\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\r\necho location of your Java installation. 1>&2\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif %ERRORLEVEL% equ 0 goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nset EXIT_CODE=%ERRORLEVEL%\r\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\r\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\r\nexit /b %EXIT_CODE%\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "examples/fabric-contract-example-gradle-kotlin/settings.gradle.kts",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\n\nrootProject.name = \"gradle-kotlin\"\n"
  },
  {
    "path": "examples/fabric-contract-example-gradle-kotlin/src/main/kotlin/org/example/MyAsset.kt",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.example\n\nimport org.hyperledger.fabric.contract.annotation.DataType\nimport org.hyperledger.fabric.contract.annotation.Property\nimport org.json.JSONObject\n\n@DataType\nclass MyAsset(@Property() var value: String?) {\n\n    fun toJSONString(): String {\n        return JSONObject(this).toString()\n    }\n\n    companion object {\n        fun fromJSONString(json: String): MyAsset {\n            val value = JSONObject(json).getString(\"value\")\n            return MyAsset(value)\n        }\n    }\n    \n}"
  },
  {
    "path": "examples/fabric-contract-example-gradle-kotlin/src/main/kotlin/org/example/MyAssetContract.kt",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.example\n\nimport org.hyperledger.fabric.contract.Context\nimport org.hyperledger.fabric.contract.ContractInterface\nimport org.hyperledger.fabric.contract.annotation.Contact\nimport org.hyperledger.fabric.contract.annotation.Contract\nimport org.hyperledger.fabric.contract.annotation.Default\nimport org.hyperledger.fabric.contract.annotation.Info\nimport org.hyperledger.fabric.contract.annotation.License\nimport org.hyperledger.fabric.contract.annotation.Transaction\n\n@Contract(name = \"MyAssetContract\",\n    info = Info(title = \"MyAsset contract\",\n                description = \"Kotlin gradle dsl and Kotlin Contract\",\n                version = \"0.0.1\",\n                license =\n                        License(name = \"Apache-2.0\",\n                                url = \"\"),\n                                contact = Contact(email = \"gradle-kotlin@example.com\",\n                                                  name = \"gradle-kotlin\",\n                                                  url = \"http://gradle-kotlin.me\")))\n@Default\nclass MyAssetContract : ContractInterface {\n\n    @Transaction\n    fun myAssetExists(ctx: Context, myAssetId: String): Boolean {\n        val buffer = ctx.stub.getState(myAssetId)\n        return (buffer != null && buffer.size > 0)\n    }\n\n    @Transaction\n    fun createMyAsset(ctx: Context, myAssetId: String, value: String) {\n        val exists = myAssetExists(ctx, myAssetId)\n        if (exists) {\n            throw RuntimeException(\"The my asset $myAssetId already exists\")\n        }\n        val asset = MyAsset(value)\n        ctx.stub.putState(myAssetId, asset.toJSONString().toByteArray(Charsets.UTF_8))\n    }\n\n    @Transaction\n    fun readMyAsset(ctx: Context, myAssetId: String): MyAsset {\n        val exists = myAssetExists(ctx, myAssetId)\n        if (!exists) {\n            throw RuntimeException(\"The my asset $myAssetId does not exist\")\n        }\n        return MyAsset.fromJSONString(ctx.stub.getState(myAssetId).toString(Charsets.UTF_8))\n    }\n\n    @Transaction\n    fun updateMyAsset(ctx: Context, myAssetId: String, newValue: String) {\n        val asset = readMyAsset(ctx, myAssetId)\n        asset.value = newValue\n        ctx.stub.putState(myAssetId, asset.toJSONString().toByteArray(Charsets.UTF_8))\n    }\n\n    @Transaction\n    fun deleteMyAsset(ctx: Context, myAssetId: String) {\n        val exists = myAssetExists(ctx, myAssetId)\n        if (!exists) {\n            throw RuntimeException(\"The my asset $myAssetId does not exist\")\n        }\n        ctx.stub.delState(myAssetId)\n    }\n\n}\n"
  },
  {
    "path": "examples/fabric-contract-example-gradle-kotlin/src/test/kotlin/org/example/MyAssetContractTest.kt",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.example\n\nimport org.junit.jupiter.api.BeforeEach\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport org.junit.jupiter.api.Assertions.*\nimport com.nhaarman.mockitokotlin2.*\n\nimport java.util.ArrayList\n\nimport org.hyperledger.fabric.contract.Context\nimport org.hyperledger.fabric.shim.ChaincodeStub\nimport org.hyperledger.fabric.shim.Chaincode.Response\nimport org.hyperledger.fabric.shim.Chaincode.Response.Status\n\nclass MyAssetContractTest {\n\n    lateinit var ctx: Context\n    lateinit var stub: ChaincodeStub\n\n    @BeforeEach\n    fun beforeEach() {\n        ctx = mock()\n        stub = mock()\n        whenever(ctx.stub).thenReturn(stub)\n        whenever(stub.getState(\"1001\")).thenReturn(\"{\\\"value\\\":\\\"my asset 1001 value\\\"}\".toByteArray(Charsets.UTF_8))\n        whenever(stub.getState(\"1002\")).thenReturn(\"{\\\"value\\\":\\\"my asset 1002 value\\\"}\".toByteArray(Charsets.UTF_8))\n    }\n\n    @Nested\n    inner class myAssetExists {\n\n        @Test\n        fun `should return true for a my asset`() {\n            val contract = MyAssetContract()\n            val result = contract.myAssetExists(ctx, \"1001\")\n            assertTrue(result)\n        }\n\n        @Test\n        fun `should return false for a my asset that does not exist (no key)`() {\n            val contract = MyAssetContract()\n            val result = contract.myAssetExists(ctx, \"1003\")\n            assertFalse(result)\n        }\n\n        @Test\n        fun `should return false for a my asset that does not exist (no data)`() {\n            val contract = MyAssetContract()\n            whenever(stub.getState(\"1003\")).thenReturn(ByteArray(0))\n            val result = contract.myAssetExists(ctx, \"1003\")\n            assertFalse(result)\n        }\n\n    }\n\n    @Nested\n    inner class createMyAsset {\n\n        @Test\n        fun `should create a my asset`() {\n            val contract = MyAssetContract()\n            contract.createMyAsset(ctx, \"1003\", \"my asset 1003 value\")\n            verify(stub, times(1)).putState(\"1003\", \"{\\\"value\\\":\\\"my asset 1003 value\\\"}\".toByteArray(Charsets.UTF_8))\n        }\n\n        @Test\n        fun `should throw an error for a my asset that already exists`() {\n            val contract = MyAssetContract()\n            val e = assertThrows(RuntimeException::class.java) { contract.createMyAsset(ctx, \"1001\", \"my asset 1001 value\") }\n            assertEquals(e.message, \"The my asset 1001 already exists\")\n        }\n\n    }\n\n    @Nested\n    inner class readMyAsset {\n\n        @Test\n        fun `should return a my asset`() {\n            val contract = MyAssetContract()\n            val asset = contract.readMyAsset(ctx, \"1001\")\n            assertEquals(\"my asset 1001 value\", asset.value)\n        }\n\n        @Test\n        fun `should throw an error for a my asset that does not exist`() {\n            val contract = MyAssetContract()\n            val e = assertThrows(RuntimeException::class.java) { contract.readMyAsset(ctx, \"1003\") }\n            assertEquals(e.message, \"The my asset 1003 does not exist\")\n        }\n\n    }\n\n    @Nested\n    inner class updateMyAsset {\n\n        @Test\n        fun `should update a my asset`() {\n            val contract = MyAssetContract()\n            contract.updateMyAsset(ctx, \"1001\", \"my asset 1001 new value\")\n            verify(stub, times(1)).putState(\"1001\", \"{\\\"value\\\":\\\"my asset 1001 new value\\\"}\".toByteArray(Charsets.UTF_8))\n        }\n\n        @Test\n        fun `should throw an error for a my asset that does not exist`() {\n            val contract = MyAssetContract()\n            val e = assertThrows(RuntimeException::class.java) { contract.updateMyAsset(ctx, \"1003\", \"my asset 1003 new value\") }\n            assertEquals(e.message, \"The my asset 1003 does not exist\")\n        }\n\n    }\n\n    @Nested\n    inner class deleteMyAsset {\n\n        @Test\n        fun `should delete a my asset`() {\n            val contract = MyAssetContract()\n            contract.deleteMyAsset(ctx, \"1001\")\n            verify(stub, times(1)).delState(\"1001\")\n        }\n\n        @Test\n        fun `should throw an error for a my asset that does not exist`() {\n            val contract = MyAssetContract()\n            val e = assertThrows(RuntimeException::class.java) { contract.deleteMyAsset(ctx, \"1003\") }\n            assertEquals(e.message, \"The my asset 1003 does not exist\")\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "examples/fabric-contract-example-maven/.gitignore",
    "content": "target"
  },
  {
    "path": "examples/fabric-contract-example-maven/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<groupId>MyAssetContract</groupId>\n\t<artifactId>MyAssetContract</artifactId>\n\t<version>1.0-SNAPSHOT</version>\n\t<properties>\n\n\t\t<!-- Generic properties -->\n\t\t<java.version>21</java.version>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>\n\n\t\t<!-- fabric-chaincode-java -->\n\t\t<fabric-chaincode-java.version>2.5.8</fabric-chaincode-java.version>\n\n\t\t<!-- Logging -->\n\t\t<logback.version>1.5.32</logback.version>\n\t\t<slf4j.version>2.0.17</slf4j.version>\n\n\t</properties>\n\t\n    <repositories>\n        <repository>\n            <id>jitpack.io</id>\n            <url>https://www.jitpack.io</url>\n        </repository>\n    </repositories>\n\n    <dependencyManagement>\n        <dependencies>\n            <dependency>\n                <groupId>org.junit</groupId>\n                <artifactId>junit-bom</artifactId>\n                <version>6.0.3</version>\n                <type>pom</type>\n                <scope>import</scope>\n            </dependency>\n        </dependencies>\n    </dependencyManagement>\n\n    <dependencies>\n\n\t\t<!-- fabric-chaincode-java -->\n\t\t<dependency>\n\t\t\t<groupId>org.hyperledger.fabric-chaincode-java</groupId>\n\t\t\t<artifactId>fabric-chaincode-shim</artifactId>\n\t\t\t<version>${fabric-chaincode-java.version}</version>\n\t\t\t<scope>compile</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.hyperledger.fabric</groupId>\n\t\t\t<artifactId>fabric-protos</artifactId>\n\t\t\t<version>0.3.7</version>\n\t\t\t<scope>compile</scope>\n\t\t</dependency>\n\n\n\t\t<!-- fabric-sdk-java -->\n\n\t\t<!-- Logging with SLF4J & LogBack -->\n\t\t<dependency>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t<artifactId>slf4j-api</artifactId>\n\t\t\t<version>${slf4j.version}</version>\n\t\t\t<scope>compile</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>ch.qos.logback</groupId>\n\t\t\t<artifactId>logback-classic</artifactId>\n\t\t\t<version>${logback.version}</version>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\t\t\n\t\t<!-- Test Artifacts -->\n\t\t<dependency>\n\t\t\t<groupId>org.junit.jupiter</groupId>\n\t\t\t<artifactId>junit-jupiter-api</artifactId>\n\t\t\t<scope>compile</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.junit.jupiter</groupId>\n\t\t\t<artifactId>junit-jupiter-params</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.junit.jupiter</groupId>\n\t\t\t<artifactId>junit-jupiter-engine</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.mockito</groupId>\n\t\t\t<artifactId>mockito-core</artifactId>\n\t\t\t<version>5.23.0</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.json</groupId>\n\t\t\t<artifactId>json</artifactId>\n\t\t\t<version>20251224</version>\n\t\t</dependency>\n\n\t</dependencies>\n\t<build>\n\t\t<sourceDirectory>src</sourceDirectory>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<artifactId>maven-surefire-plugin</artifactId>\n\t\t\t\t<version>3.5.5</version>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t<version>3.15.0</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<release>${java.version}</release>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-shade-plugin</artifactId>\n\t\t\t\t<version>3.6.2</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>shade</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<finalName>chaincode</finalName>\n\t\t\t\t\t\t\t<transformers>\n\t\t\t\t\t\t\t\t<transformer implementation=\"org.apache.maven.plugins.shade.resource.ManifestResourceTransformer\">\n\t\t\t\t\t\t\t\t\t<mainClass>org.hyperledger.fabric.contract.ContractRouter</mainClass>\n\t\t\t\t\t\t\t\t</transformer>\n\t\t\t\t\t\t\t</transformers>\n\t\t\t\t\t\t\t<filters>\n\t\t\t\t\t\t\t\t<filter>\n\t\t\t\t\t\t\t\t\t<!-- filter out signature files from signed dependencies, else repackaging fails with security ex -->\n\t\t\t\t\t\t\t\t\t<artifact>*:*</artifact>\n\t\t\t\t\t\t\t\t\t<excludes>\n\t\t\t\t\t\t\t\t\t\t<exclude>META-INF/*.SF</exclude>\n\t\t\t\t\t\t\t\t\t\t<exclude>META-INF/*.DSA</exclude>\n\t\t\t\t\t\t\t\t\t\t<exclude>META-INF/*.RSA</exclude>\n\t\t\t\t\t\t\t\t\t</excludes>\n\t\t\t\t\t\t\t\t</filter>\n\t\t\t\t\t\t\t</filters>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n\n</project>\n"
  },
  {
    "path": "examples/fabric-contract-example-maven/src/main/java/org/example/MyAsset.java",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.example;\n\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.DataType;\nimport org.hyperledger.fabric.contract.annotation.Property;\nimport org.json.JSONObject;\n\n@DataType()\npublic class MyAsset {\n\n    @Property()\n    private String value;\n\n    public MyAsset(){\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public void setValue(String value) {\n        this.value = value;\n    }\n\n    public String toJSONString() {\n        return new JSONObject(this).toString();\n    }\n\n    public static MyAsset fromJSONString(String json) {\n        String value = new JSONObject(json).getString(\"value\");\n        MyAsset asset = new MyAsset();\n        asset.setValue(value);\n        return asset;\n    }\n}\n"
  },
  {
    "path": "examples/fabric-contract-example-maven/src/main/java/org/example/MyAssetContract.java",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.example;\n\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.Default;\nimport org.hyperledger.fabric.contract.annotation.Transaction;\n\nimport org.hyperledger.fabric.contract.annotation.Contact;\nimport org.hyperledger.fabric.contract.annotation.Info;\nimport org.hyperledger.fabric.contract.annotation.License;\nimport static java.nio.charset.StandardCharsets.UTF_8;\n\n@Contract(name = \"MyAssetContract\",\n    info = @Info(title = \"MyAsset contract\",\n                description = \"Very basic Java Contract example\",\n                version = \"0.0.1\",\n                license =\n                        @License(name = \"SPDX-License-Identifier: Apache-2.0\",\n                                url = \"\"),\n                                contact =  @Contact(email = \"MyAssetContract@example.com\",\n                                                name = \"MyAssetContract\",\n                                                url = \"http://MyAssetContract.me\")))\n@Default\npublic class MyAssetContract implements ContractInterface {\n    public  MyAssetContract() {\n\n    }\n    @Transaction()\n    public boolean myAssetExists(Context ctx, String myAssetId) {\n        byte[] buffer = ctx.getStub().getState(myAssetId);\n        return (buffer != null && buffer.length > 0);\n    }\n\n    @Transaction()\n    public void createMyAsset(Context ctx, String myAssetId, String value) {\n        boolean exists = myAssetExists(ctx,myAssetId);\n        if (exists) {\n            throw new RuntimeException(\"The asset \"+myAssetId+\" already exists\");\n        }\n        MyAsset asset = new MyAsset();\n        asset.setValue(value);\n        ctx.getStub().putState(myAssetId, asset.toJSONString().getBytes(UTF_8));\n    }\n\n    @Transaction()\n    public MyAsset readMyAsset(Context ctx, String myAssetId) {\n        boolean exists = myAssetExists(ctx,myAssetId);\n        if (!exists) {\n            throw new RuntimeException(\"The asset \"+myAssetId+\" does not exist\");\n        }\n\n        MyAsset newAsset = MyAsset.fromJSONString(new String(ctx.getStub().getState(myAssetId),UTF_8));\n        return newAsset;\n    }\n\n    @Transaction()\n    public void updateMyAsset(Context ctx, String myAssetId, String newValue) {\n        boolean exists = myAssetExists(ctx,myAssetId);\n        if (!exists) {\n            throw new RuntimeException(\"The asset \"+myAssetId+\" does not exist\");\n        }\n        MyAsset asset = new MyAsset();\n        asset.setValue(newValue);\n\n        ctx.getStub().putState(myAssetId, asset.toJSONString().getBytes(UTF_8));\n    }\n\n    @Transaction()\n    public void deleteMyAsset(Context ctx, String myAssetId) {\n        boolean exists = myAssetExists(ctx,myAssetId);\n        if (!exists) {\n            throw new RuntimeException(\"The asset \"+myAssetId+\" does not exist\");\n        }\n        ctx.getStub().delState(myAssetId);\n    }\n\n}"
  },
  {
    "path": "examples/fabric-contract-example-maven/src/test/java/org/example/MyAssetContractTest.java",
    "content": "/*\n * SPDX-License-Identifier: Apache License 2.0\n */\n\npackage org.example;\nimport static java.nio.charset.StandardCharsets.UTF_8;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\nimport java.nio.charset.StandardCharsets;\n\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\n\n\npublic final class MyAssetContractTest {\n\n    @Nested\n    class AssetExists {\n        @Test\n        public void noProperAsset() {\n\n            MyAssetContract contract = new  MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            when(stub.getState(\"10001\")).thenReturn(new byte[] {});\n            boolean result = contract.myAssetExists(ctx,\"10001\");\n\n            assertFalse(result);\n        }\n\n        @Test\n        public void assetExists() {\n\n            MyAssetContract contract = new  MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            when(stub.getState(\"10001\")).thenReturn(new byte[] {42});\n            boolean result = contract.myAssetExists(ctx,\"10001\");\n\n            assertTrue(result);\n\n        }\n\n        @Test\n        public void noKey() {\n            MyAssetContract contract = new  MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            when(stub.getState(\"10002\")).thenReturn(null);\n            boolean result = contract.myAssetExists(ctx,\"10002\");\n\n            assertFalse(result);\n\n        }\n\n    }\n\n    @Nested\n    class AssetCreates {\n\n        @Test\n        public void newAssetCreate() {\n            MyAssetContract contract = new  MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            String json = \"{\\\"value\\\":\\\"TheAsset\\\"}\";\n\n            contract.createMyAsset(ctx, \"10001\", \"TheAsset\");\n\n            verify(stub).putState(\"10001\", json.getBytes(UTF_8));\n        }\n\n        @Test\n        public void alreadyExists() {\n            MyAssetContract contract = new  MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            when(stub.getState(\"10002\")).thenReturn(new byte[] { 42 });\n\n            Exception thrown = assertThrows(RuntimeException.class, () -> {\n                contract.createMyAsset(ctx, \"10002\", \"TheAsset\");\n            });\n\n            assertEquals(thrown.getMessage(), \"The asset 10002 already exists\");\n\n        }\n\n    }\n\n    @Test\n    public void assetRead() {\n        MyAssetContract contract = new  MyAssetContract();\n        Context ctx = mock(Context.class);\n        ChaincodeStub stub = mock(ChaincodeStub.class);\n        when(ctx.getStub()).thenReturn(stub);\n\n        MyAsset asset = new  MyAsset();\n        asset.setValue(\"Valuable\");\n\n        String json = asset.toJSONString();\n        when(stub.getState(\"10001\")).thenReturn(json.getBytes(StandardCharsets.UTF_8));\n\n        MyAsset returnedAsset = contract.readMyAsset(ctx, \"10001\");\n        assertEquals(returnedAsset.getValue(), asset.getValue());\n    }\n\n    @Nested\n    class AssetUpdates {\n        @Test\n        public void updateExisting() {\n            MyAssetContract contract = new  MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n            when(stub.getState(\"10001\")).thenReturn(new byte[] { 42 });\n\n            contract.updateMyAsset(ctx, \"10001\", \"updates\");\n\n            String json = \"{\\\"value\\\":\\\"updates\\\"}\";\n            verify(stub).putState(\"10001\", json.getBytes(UTF_8));\n        }\n\n        @Test\n        public void updateMissing() {\n            MyAssetContract contract = new  MyAssetContract();\n            Context ctx = mock(Context.class);\n            ChaincodeStub stub = mock(ChaincodeStub.class);\n            when(ctx.getStub()).thenReturn(stub);\n\n            when(stub.getState(\"10001\")).thenReturn(null);\n\n            Exception thrown = assertThrows(RuntimeException.class, () -> {\n                contract.updateMyAsset(ctx, \"10001\", \"TheAsset\");\n            });\n\n            assertEquals(thrown.getMessage(), \"The asset 10001 does not exist\");\n        }\n\n    }\n\n    @Test\n    public void assetDelete() {\n        MyAssetContract contract = new  MyAssetContract();\n        Context ctx = mock(Context.class);\n        ChaincodeStub stub = mock(ChaincodeStub.class);\n        when(ctx.getStub()).thenReturn(stub);\n        when(stub.getState(\"10001\")).thenReturn(null);\n\n        Exception thrown = assertThrows(RuntimeException.class, () -> {\n            contract.deleteMyAsset(ctx, \"10001\");\n        });\n\n        assertEquals(thrown.getMessage(), \"The asset 10001 does not exist\");\n    }\n\n}"
  },
  {
    "path": "examples/ledger-api/.gitignore",
    "content": ".gradle/\nbuild/\nbin/"
  },
  {
    "path": "examples/ledger-api/README.md",
    "content": "This example needs to use gradle4.6  please install this first\n\neg using sdkman\n\n`sdk install gradle 4.6`\n\n\nand then add the wrapper code before building\n\n`gradle wrapper`"
  },
  {
    "path": "examples/ledger-api/build.gradle",
    "content": "plugins {\n    id 'com.gradleup.shadow' version '9.3.1'\n    id 'java'\n}\n\nversion '0.0.1'\n\nrepositories {\n    mavenCentral()\n    maven {\n        url \"https://www.jitpack.io\"\n    }\n}\n\ndependencies {\n    implementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:2.5.8'\n    implementation 'org.json:json:20251224'\n    testImplementation platform('org.junit:junit-bom:6.0.2')\n    testImplementation 'org.junit.jupiter:junit-jupiter'\n    testImplementation 'org.assertj:assertj-core:3.27.7'\n    testImplementation 'org.mockito:mockito-core:5.21.0'\n    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'\n}\n\nshadowJar {\n    archiveBaseName = 'chaincode'\n    archiveVersion = ''\n    archiveClassifier = ''\n    duplicatesStrategy = DuplicatesStrategy.INCLUDE\n    mergeServiceFiles()\n\n    manifest {\n        attributes 'Main-Class': 'org.hyperledger.fabric.contract.ContractRouter'\n    }\n}\n\ncompileJava {\n    options.release.set(11)\n    options.compilerArgs << \"-Xlint:unchecked\" << \"-Xlint:deprecation\" << \"-parameters\"\n}\n\ntest {\n    useJUnitPlatform()\n    testLogging {\n        events \"PASSED\", \"SKIPPED\", \"FAILED\"\n    }\n}\n"
  },
  {
    "path": "examples/ledger-api/src/main/java/org/example/LedgerAPIContract.java",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.example;\n\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.Default;\nimport org.hyperledger.fabric.contract.annotation.Transaction;\n\nimport org.hyperledger.fabric.contract.annotation.Contact;\nimport org.hyperledger.fabric.contract.annotation.Info;\nimport org.hyperledger.fabric.contract.annotation.License;\nimport static java.nio.charset.StandardCharsets.UTF_8;\n\n@Contract(name = \"LedgerAPI\",\n    info = @Info(title = \"Ledger API Examples\",\n                description = \"Technical Details and use of the Ledger API\",\n                version = \"0.0.1\",\n                license =\n                        @License(name = \"SPDX-License-Identifier: Apache-2.0\",\n                                url = \"\"),\n                                contact =  @Contact(email = \"ledgerapi@example.com\",\n                                                name = \"ledgerapi\",\n                                                url = \"http://ledgerapi.me\")))\n@Default\npublic class LedgerAPIContract implements ContractInterface {\n\n    public  LedgerAPIContract() {\n\n    }\n\n\n    /**\n     * Example showing getting the world state ledger.\n     */\n    @Transaction()\n    public boolean assetExistsInWorldState(Context ctx, String myAssetId) {\n        Collection collection = Ledger.getLedger(ctx).getCollection(Collection.WORLD);\n        // check exists\n        return false;\n    }\n\n    public final static String PRIVATE_RECORDS = \"PrivateRecords\";\n\n    /**\n     * Example showing getting the a named private data collectionm.\n     */\n    @Transaction()\n    public boolean assetExistsInPrivateData(Context ctx, String myAssetId) {\n        Collection collection = Ledger.getLedger(ctx).getCollection(LedgerAPIContract.PRIVATE_RECORDS);\n\n        // check exists\n        return false;\n    }\n\n    /** \n     * Exanmple showing getting one of the organizational collections\n     */\n    @Transaction()\n    public boolean assetExistsInOrganizationPrivateData(Context ctx, String myAssetId) {\n        Collection collection = Ledger.getLedger(ctx).getCollection(Collection.organizationCollection(\"myMspId\"));\n\n        // check exists\n        return false;\n    }\n\n}"
  },
  {
    "path": "examples/ledger-api/src/main/java/org/example/MyAsset.java",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.example;\n\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.DataType;\nimport org.hyperledger.fabric.contract.annotation.Property;\nimport org.json.JSONObject;\n\n@DataType()\npublic class MyAsset {\n\n    @Property()\n    private String value;\n\n    public MyAsset(){\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public void setValue(String value) {\n        this.value = value;\n    }\n\n    public String toJSONString() {\n        return new JSONObject(this).toString();\n    }\n\n    public static MyAsset fromJSONString(String json) {\n        String value = new JSONObject(json).getString(\"value\");\n        MyAsset asset = new MyAsset();\n        asset.setValue(value);\n        return asset;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-docker/.gitignore",
    "content": "/bin/\n"
  },
  {
    "path": "fabric-chaincode-docker/Dockerfile",
    "content": "ARG JAVA_IMAGE=eclipse-temurin:25-jdk\n\nFROM ${JAVA_IMAGE} AS builder\n\nRUN apt-get update \\\n    && apt-get install -y curl zip unzip\nRUN curl -s \"https://get.sdkman.io\" | bash\n\nSHELL [\"/bin/bash\", \"-c\"]\n\nRUN . /root/.sdkman/bin/sdkman-init.sh \\\n    && sdk install gradle 9.4.1 \\\n    && sdk install maven 3.9.15\n\nFROM ${JAVA_IMAGE} AS dependencies\n\nCOPY --from=builder /root/.sdkman/candidates/gradle/current /opt/gradle\nCOPY --from=builder /root/.sdkman/candidates/maven/current /opt/maven\n\nSHELL [\"/bin/bash\", \"-c\"]\nENV PATH=\"/opt/maven/bin:/opt/gradle/bin:${PATH}\"\n\n# Coping libs, scripts and sources\nCOPY build/distributions/ /root/\n\n#Creating folders structure\nRUN mkdir -p \\\n    /root/chaincode-java/chaincode/src \\\n    /root/chaincode-java/chaincode/build/out \\\n    /root/chaincode-java/shim-src/fabric-chaincode-integration-test \\\n    /root/chaincode-java/shim-src/fabric-chaincode-docker\n\n#Making scripts runnable\nRUN chmod +x /root/chaincode-java/start /root/chaincode-java/build.sh\n\n# Build protos and shim jar and installing them to maven local and gradle cache\nWORKDIR /root/chaincode-java/shim-src\nRUN gradle \\\n    clean \\\n    fabric-chaincode-shim:build \\\n    fabric-chaincode-shim:publishToMavenLocal \\\n    -x javadoc \\\n    -x test \\\n    -x pmdMain \\\n    -x pmdTest \\\n    -x spotlessCheck\n\nWORKDIR /root/chaincode-java \n# Run the Gradle and Maven commands to generate the wrapper variants\n# of each tool\n# Gradle doesn't run without settings.gradle file, so create one\nRUN touch settings.gradle \\\n    && gradle wrapper \\\n    && ./gradlew wrapper \\\n    && mvn -N wrapper:wrapper\n\n# Creating final javaenv image which will include all required\n# dependencies to build and compile java chaincode\nFROM ${JAVA_IMAGE}\n\nRUN apt-get update \\\n    && apt-get install -y zip unzip \\\n    && apt-get clean \\\n    && rm -rf /var/lib/apt/lists/* \\\n    && mkdir -p /chaincode/input \\\n    && mkdir -p /chaincode/output\n\nSHELL [\"/bin/bash\", \"-c\"]\n\n# Copy setup scripts, and the cached dependencies\nCOPY --from=dependencies /root/chaincode-java /root/chaincode-java\nCOPY --from=dependencies /root/.gradle /root/.gradle\nCOPY --from=dependencies /root/.m2 /root/.m2\n\nWORKDIR /root/chaincode-java\n"
  },
  {
    "path": "fabric-chaincode-docker/README.md",
    "content": "# Quick reference\n\n- **Maintained by**:  \n  [The Fabric Java chaincode maintainers](https://github.com/hyperledger/fabric-chaincode-java)\n\n# Overview\n\nThis image is used by the default [Hyperledger Fabric](https://hyperledger-fabric.readthedocs.io/) chaincode builder when deploying Java smart contracts. It is not intended for use independently of Hyperledger Fabric.\n\n# Image variants\n\nDetailed information on image tags, interoperability, and supported Java versions can be found in the [compatibility](https://github.com/hyperledger/fabric-chaincode-java/blob/main/COMPATIBILITY.md) documentation.\n\n# License\n\nThis image is provided under the [Apache-2.0](https://github.com/hyperledger/fabric-chaincode-java/blob/main/LICENSE) license.\n"
  },
  {
    "path": "fabric-chaincode-docker/build.gradle",
    "content": "/*\n * Copyright IBM Corp. 2018 All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\nplugins {\n    id 'com.bmuschko.docker-remote-api' version '10.0.0'\n}\n\nrepositories {\n    mavenCentral()\n}\n\nimport com.bmuschko.gradle.docker.tasks.image.*\n\ntasks.register('copyLib', Copy) {\n    dependsOn ':fabric-chaincode-shim:build'\n    from project(':fabric-chaincode-shim').configurations.runtimeClasspath\n    into('build/distributions/chaincode-java/lib')\n}\n\ntasks.register('copyShimJar', Copy) {\n    dependsOn copyLib\n    from project(':fabric-chaincode-shim').jar\n    into('build/distributions/chaincode-java/lib')\n}\n\ntasks.register('copyStartScript', Copy) {\n    dependsOn copyShimJar\n    from('start')\n    into('build/distributions/chaincode-java')\n}\n\ntasks.register('copyBuildScript', Copy) {\n    dependsOn copyStartScript\n    from('build.sh')\n    into('build/distributions/chaincode-java')\n}\n\ntasks.register('copyAllDeps', Copy) {\n    dependsOn copyBuildScript\n    copy {\n        from project(':fabric-chaincode-shim').getProjectDir()\n        into('build/distributions/chaincode-java/shim-src/fabric-chaincode-shim/')\n    }\n\n    copy {\n        from project.getParent().file(\"build.gradle\")\n        into('build/distributions/chaincode-java/shim-src/')\n    }\n\n    copy {\n        from project.getParent().file(\"settings.gradle\")\n        into('build/distributions/chaincode-java/shim-src/')\n    }\n}\n\ntasks.register('buildImage', DockerBuildImage) {\n    dependsOn copyAllDeps\n    inputDir = project.file('Dockerfile').parentFile\n    images = ['hyperledger/fabric-javaenv', 'hyperledger/fabric-javaenv:2.5', 'hyperledger/fabric-javaenv:2.5.9']\n}\n"
  },
  {
    "path": "fabric-chaincode-docker/build.sh",
    "content": "#!/usr/bin/env bash\nset -ex\n\nINPUT_DIR=/chaincode/input\nOUTPUT_DIR=/chaincode/output\nTMP_DIR=$(mktemp -d)\n\nNUM_JARS=$(find ${INPUT_DIR} -name \"*.jar\" | wc -l)\n\nbuildGradle() {\n    echo \"Copying from $1 to ${TMP_DIR}\"\n    cd $1\n    tar cf - . | (cd ${TMP_DIR}; tar xf -)\n    cd ${TMP_DIR}\n    echo \"Gradle build\"\n    if [ -f ./gradlew ]; then\n      chmod +x ./gradlew\n      ./gradlew build shadowJar -x test\n    else\n      /root/chaincode-java/gradlew build shadowJar -x test\n    fi\n    retval=$?\n    if [ $retval -ne 0 ]; then\n      exit $retval\n    fi\n    cp build/libs/chaincode.jar $2\n    retval=$?\n    if [ $retval -ne 0 ]; then\n      exit $retval\n    fi\n    touch $2/.uberjar\n    cd \"$SAVED\" >/dev/null\n}\n\nbuildMaven() {\n    echo \"Copying from $1 to ${TMP_DIR}\"\n    cd $1\n    tar cf - . | (cd ${TMP_DIR}; tar xf -)\n    cd ${TMP_DIR}\n    echo \"Maven build\"\n\n    if [ -f ./mvnw ]; then\n      chmod +x ./mvnw      \n    else\n      cp -r /root/chaincode-java/.mvn .\n      cp /root/chaincode-java/mvnw .\n    fi\n    ./mvnw compile package -DskipTests -Dmaven.test.skip=true\n    \n    retval=$?\n    if [ $retval -ne 0 ]; then\n      exit $retval\n    fi\n    cp target/chaincode.jar $2\n    retval=$?\n    if [ $retval -ne 0 ]; then\n      exit $retval\n    fi\n    touch $2/.uberjar\n    cd \"$SAVED\" >/dev/null\n}\n\nfor DIR in ${INPUT_DIR} ${INPUT_DIR}/src; do\n    if [ -f ${DIR}/build.gradle -o -f ${DIR}/build.gradle.kts ]; then\n        buildGradle ${DIR} ${OUTPUT_DIR}\n        exit 0\n    elif [ -f ${DIR}/pom.xml ]; then\n        buildMaven ${DIR} ${OUTPUT_DIR}\n        exit 0\n    fi\ndone\n\nif [ ${NUM_JARS} -eq 0 ]; then\n    >&2 echo \"Not build.gradle nor pom.xml found in chaincode source, don't know how to build chaincode\"\n    >&2 echo \"Project folder content:\"\n    >&2 find ${INPUT_DIR} -name \"*\" -exec ls -ld '{}' \\;\n    exit 255\nelse\n    cd ${INPUT_DIR} && tar cf - $(find . -name \"*.jar\") | (cd ${OUTPUT_DIR} && tar xvf -)\nfi"
  },
  {
    "path": "fabric-chaincode-docker/start",
    "content": "#!/usr/bin/env bash\nset -ex\n\nROOT_DIR=/root/chaincode-java\nLIB_DIR=${ROOT_DIR}/lib\nCHAINCODE_DIR=${ROOT_DIR}/chaincode\nLIB_JARS=$(find ${LIB_DIR} -name \"*.jar\" | paste -s -d \":\" -)\nCHAINCODE_JARS=$(find ${CHAINCODE_DIR} -name \"*.jar\" | paste -s -d \":\" -)\nNUM_CHAINCODE_JARS=$(find ${CHAINCODE_DIR} -name \"*.jar\" | wc -l)\n\nJAVA_OPTS=\"-XshowSettings\"\n\nif [ -f ${CHAINCODE_DIR}/.uberjar ]; then\n    if [ ${NUM_CHAINCODE_JARS} -ne 1 ]; then\n        >&2 echo \"Cannot start uber JAR as more than one JAR file was found in the chaincode directory\"\n        exit 255\n    fi\n    exec java ${JAVA_OPTS} -jar ${CHAINCODE_JARS} \"$@\"\nelse\n    exec java ${JAVA_OPTS} -cp ${CHAINCODE_JARS}:${LIB_JARS} org.hyperledger.fabric.contract.ContractRouter \"$@\"\nfi"
  },
  {
    "path": "fabric-chaincode-integration-test/.gitignore",
    "content": "repository\n_cfg\n*.tar.gz\nlog.txt\n"
  },
  {
    "path": "fabric-chaincode-integration-test/build.gradle",
    "content": "dependencies {\n    implementation project(':fabric-chaincode-docker')\n    implementation project(':fabric-chaincode-shim')\n    implementation 'org.json:json:20251224'\n}\n\n\n test {\n    // Always run tests, even when nothing changed.\n    dependsOn 'cleanTest'\n\n    // Show test results.\n    testLogging {\n        events \"passed\", \"skipped\", \"failed\"\n        showExceptions = true\n        showCauses = true\n        showStandardStreams = true\n        exceptionFormat = \"full\"\n\n    }\n }\n\ntasks.register('getLatestDockerImages') {\n    doLast {\n        providers.exec {\n            workingDir \".\"\n            commandLine \"sh\", \"-c\", \"./getDockerImages.sh\"\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-integration-test/chaincodebootstrap.gradle",
    "content": "allprojects {\n    apply plugin: 'maven-publish'\n\n    publishing {\n        repositories {\n            maven {\n                name = 'fabric'\n                url = \"file:$chaincodeRepoDir\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/bare-gradle/build.gradle",
    "content": "plugins {\n    id 'com.gradleup.shadow' version '9.3.1'\n    id 'java'\n}\n\ngroup 'org.hyperledger.fabric-chaincode-java'\nversion '1.0-SNAPSHOT'\n\ncompileJava {\n    options.release = 11\n}\n\nrepositories {\n    mavenCentral()\n    maven {\n      url \"$projectDir/repository\"\n    }\n}\n\ndependencies {\n    implementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:2.5.9'\n    implementation 'org.hyperledger.fabric:fabric-protos:0.3.7'\n}\n\nshadowJar {\n    archiveBaseName = 'chaincode'\n    archiveVersion = ''\n    archiveClassifier = ''\n    duplicatesStrategy = DuplicatesStrategy.INCLUDE\n    mergeServiceFiles()\n\n    manifest {\n        attributes 'Main-Class': 'org.hyperledger.fabric.contract.ContractRouter'\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/bare-gradle/src/main/java/org/hyperledger/fabric/example/BareGradle.java",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.example;\n\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.annotation.Contact;\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.Default;\nimport org.hyperledger.fabric.contract.annotation.Info;\nimport org.hyperledger.fabric.contract.annotation.License;\nimport org.hyperledger.fabric.contract.annotation.Transaction;\n\n@Contract(name = \"BareGradle\",\n    info = @Info(title = \"BareGradle contract\",\n                description = \"Contract but using all the APIs\",\n                version = \"0.0.1\",\n                license =\n                        @License(name = \"SPDX-License-Identifier: Apache-2.0\",\n                                url = \"\"),\n                                contact =  @Contact(email = \"fred@example.com\",\n                                                name = \"fred\",\n                                                url = \"http://fred.example.com\")))\n@Default\npublic class BareGradle implements ContractInterface {\n    public BareGradle() {\n\n    }\n\n    @Transaction()\n    public String whoami(Context ctx){\n       return this.getClass().getSimpleName();\n    }\n}"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/bare-gradle/src/main/resources/config.props",
    "content": "MAX_INBOUND_MESSAGE_SIZE=4000\nCHAINCODE_METRICS_ENABLED=true\nTP_CORE_POOL_SIZE=4\nTP_MAX_POOL_SIZE=4\nTP_QUEUE_SIZE=4000\n "
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/bare-maven/.gitignore",
    "content": "target"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/bare-maven/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<groupId>MyAssetContract</groupId>\n\t<artifactId>MyAssetContract</artifactId>\n\t<version>1.0-SNAPSHOT</version>\n\t<properties>\n\n\t\t<!-- Generic properties -->\n\t\t<java.version>11</java.version>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>\n\n\t\t<!-- fabric-chaincode-java -->\n\t\t<fabric-chaincode-java.version>2.5.9</fabric-chaincode-java.version>\n\n\t</properties>\n\t\n    <repositories>\n        <repository>\n            <id>jitpack.io</id>\n            <url>https://www.jitpack.io</url>\n        </repository>\n\t\t<repository>\n\t\t\t<id>localfabirc</id>\n\t\t\t<url>file://${project.basedir}/repository</url>\n\t\t</repository>\t\t\t\n    </repositories>\n\n\t<dependencies>\n\n\t\t<!-- fabric-chaincode-java -->\n\t\t<dependency>\n\t\t\t<groupId>org.hyperledger.fabric-chaincode-java</groupId>\n\t\t\t<artifactId>fabric-chaincode-shim</artifactId>\n\t\t\t<version>${fabric-chaincode-java.version}</version>\n\t\t\t<scope>compile</scope>\n\t\t</dependency>\n\n\t</dependencies>\n\t<build>\n\t\t<sourceDirectory>src</sourceDirectory>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t<version>3.15.0</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<release>${java.version}</release>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-shade-plugin</artifactId>\n\t\t\t\t<version>3.6.2</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>shade</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<finalName>chaincode</finalName>\n\t\t\t\t\t\t\t<transformers>\n\t\t\t\t\t\t\t\t<transformer implementation=\"org.apache.maven.plugins.shade.resource.ServicesResourceTransformer\"/>\n\t\t\t\t\t\t\t\t<transformer implementation=\"org.apache.maven.plugins.shade.resource.ManifestResourceTransformer\">\n\t\t\t\t\t\t\t\t\t<mainClass>org.hyperledger.fabric.contract.ContractRouter</mainClass>\n\t\t\t\t\t\t\t\t</transformer>\n\t\t\t\t\t\t\t</transformers>\n\t\t\t\t\t\t\t<filters>\n\t\t\t\t\t\t\t\t<filter>\n\t\t\t\t\t\t\t\t\t<!-- filter out signature files from signed dependencies, else repackaging fails with security ex -->\n\t\t\t\t\t\t\t\t\t<artifact>*:*</artifact>\n\t\t\t\t\t\t\t\t\t<excludes>\n\t\t\t\t\t\t\t\t\t\t<exclude>META-INF/*.SF</exclude>\n\t\t\t\t\t\t\t\t\t\t<exclude>META-INF/*.DSA</exclude>\n\t\t\t\t\t\t\t\t\t\t<exclude>META-INF/*.RSA</exclude>\n\t\t\t\t\t\t\t\t\t</excludes>\n\t\t\t\t\t\t\t\t</filter>\n\t\t\t\t\t\t\t</filters>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/bare-maven/src/main/java/org/hyperledger/fabric/example/BareMaven.java",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.example;\n\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.annotation.Contact;\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.Default;\nimport org.hyperledger.fabric.contract.annotation.Info;\nimport org.hyperledger.fabric.contract.annotation.License;\nimport org.hyperledger.fabric.contract.annotation.Transaction;\n\n@Contract(name = \"BareMaven\",\n    info = @Info(title = \"BareGradle contract\",\n                description = \"Contract but using all the APIs\",\n                version = \"0.0.1\",\n                license =\n                        @License(name = \"SPDX-License-Identifier: Apache-2.0\",\n                                url = \"\"),\n                                contact =  @Contact(email = \"fred@example.com\",\n                                                name = \"fred\",\n                                                url = \"http://fred.example.com\")))\n@Default\npublic class BareMaven implements ContractInterface {\n    public BareMaven() {\n\n    }\n\n    @Transaction()\n    public String whoami(Context ctx){\n       return this.getClass().getSimpleName();\n    }\n}"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/bare-maven/src/main/resources/config.props",
    "content": "MAX_INBOUND_MESSAGE_SIZE=4000\nCHAINCODE_METRICS_ENABLED=true\nTP_CORE_POOL_SIZE=4\nTP_MAX_POOL_SIZE=4\nTP_QUEUE_SIZE=4000\n "
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/fabric-ledger-api/build.gradle",
    "content": "plugins {\n    id 'com.gradleup.shadow' version '9.3.1'\n    id 'java'\n}\n\ngroup 'org.hyperledger.fabric-chaincode-java'\nversion ''\n\ncompileJava {\n    options.release = 11\n}\n\nrepositories {\n    mavenCentral()\n    maven {\n      url \"$projectDir/repository\"\n    }\n}\n\ndependencies {\n    implementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:2.5.9'\n    implementation 'org.hyperledger.fabric:fabric-protos:0.3.7'\n}\n\nshadowJar {\n    archiveBaseName = 'chaincode'\n    archiveVersion = ''\n    archiveClassifier = ''\n    duplicatesStrategy = DuplicatesStrategy.INCLUDE\n    mergeServiceFiles()\n\n    manifest {\n        attributes 'Main-Class': 'org.hyperledger.fabric.contract.ContractRouter'\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/fabric-ledger-api/gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.14.3-bin.zip\nnetworkTimeout=10000\nvalidateDistributionUrl=true\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/fabric-ledger-api/gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n# SPDX-License-Identifier: Apache-2.0\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\n# This is normally unused\n# shellcheck disable=SC2034\nAPP_BASE_NAME=${0##*/}\n# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)\nAPP_HOME=$( cd -P \"${APP_HOME:-./}\" > /dev/null && printf '%s\n' \"$PWD\" ) || exit\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    if ! command -v java >/dev/null 2>&1\n    then\n        die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Collect all arguments for the java command:\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,\n#     and any embedded shellness will be escaped.\n#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be\n#     treated as '${Hostname}' itself on the command line.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/fabric-ledger-api/gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n@rem SPDX-License-Identifier: Apache-2.0\r\n@rem\r\n\r\n@if \"%DEBUG%\"==\"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\r\n@rem This is normally unused\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif %ERRORLEVEL% equ 0 goto execute\r\n\r\necho. 1>&2\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2\r\necho. 1>&2\r\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\r\necho location of your Java installation. 1>&2\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho. 1>&2\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2\r\necho. 1>&2\r\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\r\necho location of your Java installation. 1>&2\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif %ERRORLEVEL% equ 0 goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nset EXIT_CODE=%ERRORLEVEL%\r\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\r\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\r\nexit /b %EXIT_CODE%\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/fabric-ledger-api/settings.gradle",
    "content": "rootProject.name = 'fabric-chaincode-example-sacc'\n\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/fabric-ledger-api/src/main/java/org/hyperledger/fabric/example/AllLedgerAPI.java",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.example;\n\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.annotation.Contact;\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.Default;\nimport org.hyperledger.fabric.contract.annotation.Info;\nimport org.hyperledger.fabric.contract.annotation.License;\nimport org.hyperledger.fabric.contract.annotation.Transaction;\nimport org.hyperledger.fabric.ledger.Ledger;\n\n@Contract(name = \"AllLedgerAPI\",\n    info = @Info(title = \"AllLedgerAPI contract\",\n                description = \"Contract but using all the Ledger APIs\",\n                version = \"0.0.1\",\n                license =\n                        @License(name = \"SPDX-License-Identifier: Apache-2.0\",\n                                url = \"\"),\n                                contact =  @Contact(email = \"fred@example.com\",\n                                                name = \"fred\",\n                                                url = \"http://fred.example.com\")))\n@Default\npublic class AllLedgerAPI implements ContractInterface {\n    \n    public AllLedgerAPI() {\n\n    }\n\n    @Transaction()\n    public void accessLedgers(Context ctx){\n        Ledger ledger = Ledger.getLedger(ctx);\n        \n        // not much else can be done for the moment\n    }\n\n    \n}"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/fabric-shim-api/build.gradle",
    "content": "plugins {\n    id 'com.gradleup.shadow' version '9.3.1'\n    id 'java'\n}\n\ngroup 'org.hyperledger.fabric-chaincode-java'\nversion '1.0-SNAPSHOT'\n\ncompileJava {\n    options.release = 11\n}\n\nrepositories {\n    mavenCentral()\n    maven {\n      url \"$projectDir/repository\"\n    }\n}\n\ndependencies {\n    implementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:2.5.9'\n    implementation 'org.hyperledger.fabric:fabric-protos:0.3.7'\n    implementation 'commons-logging:commons-logging:1.3.5'\n    implementation 'com.google.code.gson:gson:2.13.2'\n}\n\nshadowJar {\n    archiveBaseName = 'chaincode'\n    archiveVersion = ''\n    archiveClassifier = ''\n    duplicatesStrategy = DuplicatesStrategy.INCLUDE\n    mergeServiceFiles()\n\n    manifest {\n        attributes 'Main-Class': 'org.hyperledger.fabric.contract.ContractRouter'\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/fabric-shim-api/gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.14.3-bin.zip\nnetworkTimeout=10000\nvalidateDistributionUrl=true\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/fabric-shim-api/gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n# SPDX-License-Identifier: Apache-2.0\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\n# This is normally unused\n# shellcheck disable=SC2034\nAPP_BASE_NAME=${0##*/}\n# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)\nAPP_HOME=$( cd -P \"${APP_HOME:-./}\" > /dev/null && printf '%s\\n' \"$PWD\" ) || exit\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=\"\\\\\\\"\\\\\\\"\"\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    if ! command -v java >/dev/null 2>&1\n    then\n        die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Collect all arguments for the java command:\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,\n#     and any embedded shellness will be escaped.\n#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be\n#     treated as '${Hostname}' itself on the command line.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        -jar \"$APP_HOME/gradle/wrapper/gradle-wrapper.jar\" \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/fabric-shim-api/gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n@rem SPDX-License-Identifier: Apache-2.0\r\n@rem\r\n\r\n@if \"%DEBUG%\"==\"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\r\n@rem This is normally unused\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif %ERRORLEVEL% equ 0 goto execute\r\n\r\necho. 1>&2\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2\r\necho. 1>&2\r\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\r\necho location of your Java installation. 1>&2\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho. 1>&2\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2\r\necho. 1>&2\r\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\r\necho location of your Java installation. 1>&2\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" -jar \"%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\" %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif %ERRORLEVEL% equ 0 goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nset EXIT_CODE=%ERRORLEVEL%\r\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\r\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\r\nexit /b %EXIT_CODE%\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/fabric-shim-api/settings.gradle",
    "content": "rootProject.name = 'fabric-chaincode-example-sacc'\n\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/fabric-shim-api/src/main/java/org/hyperledger/fabric/example/AllAPI.java",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.example;\n\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.annotation.Contact;\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.Default;\nimport org.hyperledger.fabric.contract.annotation.Info;\nimport org.hyperledger.fabric.contract.annotation.License;\nimport org.hyperledger.fabric.contract.annotation.Transaction;\nimport org.hyperledger.fabric.metrics.Metrics;\nimport org.hyperledger.fabric.metrics.MetricsProvider;\nimport org.hyperledger.fabric.shim.ledger.*;\nimport org.hyperledger.fabric.shim.*;\nimport static java.nio.charset.StandardCharsets.UTF_8;\n\n@Contract(name = \"AllAPI\",\n    info = @Info(title = \"AllAPI contract\",\n                description = \"Contract but using all the APIs\",\n                version = \"0.0.1\",\n                license =\n                        @License(name = \"SPDX-License-Identifier: Apache-2.0\",\n                                url = \"\"),\n                                contact =  @Contact(email = \"fred@example.com\",\n                                                name = \"fred\",\n                                                url = \"http://fred.example.com\")))\n@Default\npublic class AllAPI implements ContractInterface {\n    public AllAPI() {\n\n    }\n\n    @Transaction()\n    public void putBulkStates(Context ctx){\n        for (int x=100; x<200; x++){\n            String key = \"key\"+x;\n            String value = \"value:\"+x;\n\n            putState(ctx,key,value);\n        }\n    }\n\n    @Transaction()\n    public void putState(Context ctx, String key, String payload){\n        ChaincodeStub stub = ctx.getStub();\n        stub.putState(key,payload.getBytes(UTF_8));\n    }\n\n    @Transaction()\n    public void putStateComposite(Context ctx, String key[], String payload){\n        String composite = new CompositeKey(\"composite\",key).toString();\n        this.putState(ctx,composite,payload);\n    }\n\n    @Transaction()\n    public void getState(Context ctx, String key, String payload){\n        ChaincodeStub stub = ctx.getStub();\n        String result = stub.getStringState(key);\n        if (!result.equals(payload)){\n            String msg = \"GetState::[\"+key+\"] Expected \"+payload+\" got \"+result;\n            System.out.println(msg);\n            throw new RuntimeException(msg);\n        }\n    }\n\n    @Transaction()\n    public int getByRange(Context ctx, String start, String end){\n        ChaincodeStub stub = ctx.getStub();\n        System.out.println(\"getByRange>>\");\n        QueryResultsIterator<KeyValue> qri = stub.getStateByRange(start,end);\n        int count=0;\n        for (KeyValue kv : qri){\n            kv.getKey();\n            kv.getStringValue();\n            count++;\n            System.out.println(\"[\"+kv.getKey()+\"] \"+kv.getStringValue());\n        }\n        System.out.println(\"getByRange<<\");\n        return count;\n    }\n\n    @Transaction()\n    public String getByRangePaged(Context ctx, String start, String end, int pageSize, String bookmark){\n        ChaincodeStub stub = ctx.getStub();\n        System.out.println(\"getByRangePaged>>\");\n        QueryResultsIteratorWithMetadata<KeyValue> qri = stub.getStateByRangeWithPagination(start,end,pageSize,bookmark);\n        for (KeyValue kv : qri){\n            kv.getKey();\n            kv.getStringValue();\n            System.out.println(\"[\"+kv.getKey()+\"] \"+kv.getStringValue());\n        }\n\n        String newbookmark = qri.getMetadata().getBookmark();\n        int records = qri.getMetadata().getFetchedRecordsCount();\n        System.out.println(newbookmark+\" @ \"+records);\n\n        System.out.println(\"getByRangePaged<<\");\n        return newbookmark;\n    }\n    \n    @Transaction()\n    public String getMetricsProviderName(Context ctx){\n        final MetricsProvider provider = Metrics.getProvider();\n        final String name = provider.getClass().getName();\n        return name;\n    }\n\n}"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/fabric-shim-api/src/main/java/org/hyperledger/fabric/example/EndorsementCC.java",
    "content": "package org.hyperledger.fabric.example;\n\nimport static java.nio.charset.StandardCharsets.UTF_8;\n\nimport java.util.List;\n\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.Transaction;\nimport org.hyperledger.fabric.shim.ext.sbe.StateBasedEndorsement;\nimport org.hyperledger.fabric.shim.ext.sbe.impl.StateBasedEndorsementFactory;\n\nimport com.google.gson.JsonArray;\n\n@Contract()\npublic class EndorsementCC implements ContractInterface {\n\n    private static Log _logger = LogFactory.getLog(EndorsementCC.class);\n   \n    public void setup(Context ctx) {\n            _logger.info(\"Init java EndorsementCC\");\n            ctx.getStub().putStringState(\"pub\", \"foo\");\n            _logger.info(\"Init done\");\n    }\n\n    @Transaction()\n    public void addorgs(Context ctx, String type, String orgs) {\n\n        _logger.info(\"Invoking addOrgs\");\n\n        byte[] epBytes;\n        if (\"pub\".equals(type)) {\n            epBytes = ctx.getStub().getStateValidationParameter(\"pub\");\n        } else if (\"priv\".equals(type)) {\n            epBytes = ctx.getStub().getPrivateDataValidationParameter(\"col\", \"priv\");\n        } else {\n            throw new RuntimeException(\"Unknown key specified\");\n        }\n\n        StateBasedEndorsement ep = StateBasedEndorsementFactory.getInstance().newStateBasedEndorsement(epBytes);\n        ep.addOrgs(StateBasedEndorsement.RoleType.RoleTypePeer, orgs);\n        epBytes = ep.policy();\n        if (\"pub\".equals(type)) {\n            ctx.getStub().setStateValidationParameter(\"pub\", epBytes);\n        } else {\n            ctx.getStub().setPrivateDataValidationParameter(\"col\", \"priv\", epBytes);\n        }\n\n\n    }\n    \n    @Transaction()\n    public void delorgs(Context ctx, String type, String orgs) {\n    \n            _logger.info(\"Invoking delOrgs\");\n\n\n            byte[] epBytes;\n            if (\"pub\".equals(type)) {\n                epBytes = ctx.getStub().getStateValidationParameter(\"pub\");\n            } else if (\"priv\".equals(type)) {\n                epBytes = ctx.getStub().getPrivateDataValidationParameter(\"col\", \"priv\");\n            } else {\n                throw new RuntimeException(\"Unknown key specified\");\n            }\n\n            StateBasedEndorsement ep = StateBasedEndorsementFactory.getInstance().newStateBasedEndorsement(epBytes);\n            // delete organizations from the endorsement policy of that key\n            ep.delOrgs(orgs);\n            epBytes = ep.policy();\n            if (\"pub\".equals(type)) {\n                ctx.getStub().setStateValidationParameter(\"pub\", epBytes);\n            } else {\n                ctx.getStub().setPrivateDataValidationParameter(\"col\", \"priv\", epBytes);\n            }\n\n            ctx.getStub().setStateValidationParameter(\"endorsed_state\", epBytes);\n\n    }\n\n    @Transaction()\n    public String listorgs(Context ctx, String type) {\n     \n            _logger.info(\"Invoking listOrgs\");\n\n            byte[] epBytes;\n            if (\"pub\".equals(type)) {\n                epBytes = ctx.getStub().getStateValidationParameter(\"pub\");\n            } else if (\"priv\".equals(type)) {\n                epBytes = ctx.getStub().getPrivateDataValidationParameter(\"col\", \"priv\");\n            } else {\n                throw new RuntimeException(\"Unknown key specified\");\n            }\n            StateBasedEndorsement ep = StateBasedEndorsementFactory.getInstance().newStateBasedEndorsement(epBytes);\n\n            List<String> orgs = ep.listOrgs();\n            JsonArray orgsList = new JsonArray();\n            orgs.forEach(org -> orgsList.add(org));\n\n            String s = orgsList.toString();\n            _logger.info(\"orgsList \"+s);\n            \n            return orgsList.toString();\n\n    }\n    @Transaction()\n    public void delEP(Context ctx, String type) {\n        \n            _logger.info(\"Invoking delEP\");\n\n            if (\"pub\".equals(type)) {\n                ctx.getStub().setStateValidationParameter(\"pub\", null);\n            } else if (\"priv\".equals(type)) {\n                ctx.getStub().setPrivateDataValidationParameter(\"col\", \"priv\", null);\n            } else {\n                throw new RuntimeException(\"Unknown key specified\");\n            }\n            \n    }\n    @Transaction()\n    public void setval(Context ctx, String type, String value) {\n            _logger.info(\"Invoking setVal\");\n\n            if (\"pub\".equals(type)) {\n                ctx.getStub().putStringState(\"pub\", value);\n            } else if (\"priv\".equals(type)) {\n                ctx.getStub().putPrivateData(\"col\", \"priv\",value);\n            } else {\n               throw new RuntimeException(\"Unknown key specified\");\n            }\n    }\n    @Transaction()\n    public String getval(Context ctx, String type) {\n            _logger.info(\"Invoking getVal\");\n            byte[]  buffer;\n            if (\"pub\".equals(type)) {\n                buffer =  (ctx.getStub().getState(\"pub\"));\n            } else if (\"priv\".equals(type)) {\n               buffer = (ctx.getStub().getPrivateData(\"col\", \"priv\"));\n            } else {\n                throw new RuntimeException(\"Unknown key specified\");\n            }\n            \n     \n            String value = new String(buffer,UTF_8);\n            return value;\n    }\n\n    @Transaction()\n    public void deleteval(Context ctx, String type) {\n        _logger.info(\"Invoking deleteval\");\n\n        if (\"pub\".equals(type)) {\n            ctx.getStub().delState(\"pub\");\n        } else if (\"priv\".equals(type)) {\n            ctx.getStub().delPrivateData(\"col\", \"priv\");\n        } else {\n            throw new RuntimeException(\"Unknown key specified\");\n        }\n    }\n\n    @Transaction(intent = Transaction.TYPE.EVALUATE)\n    public boolean recordExists(Context ctx, String type) {\n        _logger.info(\"Invoking recordExists\");\n\n        if (\"pub\".equals(type)) {\n            byte[] buffer = ctx.getStub().getState(\"pub\");\n            return (buffer != null && buffer.length > 0);\n        } else if (\"priv\".equals(type)) {\n            byte[] buffer = ctx.getStub().getPrivateDataHash(\"col\", \"priv\");\n            return (buffer != null && buffer.length > 0);\n        } else {\n            throw new RuntimeException(\"Unknown key specified\");\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/fabric-shim-api/src/main/resources/config.props",
    "content": "MAX_INBOUND_MESSAGE_SIZE=4000\nCHAINCODE_METRICS_ENABLED=true\nTP_CORE_POOL_SIZE=4\nTP_MAX_POOL_SIZE=4\nTP_QUEUE_SIZE=4000\n "
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/wrapper-maven/.gitignore",
    "content": "target"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/wrapper-maven/.mvn/wrapper/maven-wrapper.properties",
    "content": "wrapperVersion=3.3.4\ndistributionType=bin\ndistributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip\nwrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/wrapper-maven/mvnw",
    "content": "#!/bin/sh\n# ----------------------------------------------------------------------------\n# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n# ----------------------------------------------------------------------------\n\n# ----------------------------------------------------------------------------\n# Apache Maven Wrapper startup batch script, version 3.3.4\n#\n# Required ENV vars:\n# ------------------\n#   JAVA_HOME - location of a JDK home dir\n#\n# Optional ENV vars\n# -----------------\n#   MAVEN_OPTS - parameters passed to the Java VM when running Maven\n#     e.g. to debug Maven itself, use\n#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000\n#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files\n# ----------------------------------------------------------------------------\n\nif [ -z \"$MAVEN_SKIP_RC\" ]; then\n\n  if [ -f /usr/local/etc/mavenrc ]; then\n    . /usr/local/etc/mavenrc\n  fi\n\n  if [ -f /etc/mavenrc ]; then\n    . /etc/mavenrc\n  fi\n\n  if [ -f \"$HOME/.mavenrc\" ]; then\n    . \"$HOME/.mavenrc\"\n  fi\n\nfi\n\n# OS specific support.  $var _must_ be set to either true or false.\ncygwin=false\ndarwin=false\nmingw=false\ncase \"$(uname)\" in\nCYGWIN*) cygwin=true ;;\nMINGW*) mingw=true ;;\nDarwin*)\n  darwin=true\n  # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home\n  # See https://developer.apple.com/library/mac/qa/qa1170/_index.html\n  if [ -z \"$JAVA_HOME\" ]; then\n    if [ -x \"/usr/libexec/java_home\" ]; then\n      JAVA_HOME=\"$(/usr/libexec/java_home)\"\n      export JAVA_HOME\n    else\n      JAVA_HOME=\"/Library/Java/Home\"\n      export JAVA_HOME\n    fi\n  fi\n  ;;\nesac\n\nif [ -z \"$JAVA_HOME\" ]; then\n  if [ -r /etc/gentoo-release ]; then\n    JAVA_HOME=$(java-config --jre-home)\n  fi\nfi\n\n# For Cygwin, ensure paths are in UNIX format before anything is touched\nif $cygwin; then\n  [ -n \"$JAVA_HOME\" ] \\\n    && JAVA_HOME=$(cygpath --unix \"$JAVA_HOME\")\n  [ -n \"$CLASSPATH\" ] \\\n    && CLASSPATH=$(cygpath --path --unix \"$CLASSPATH\")\nfi\n\n# For Mingw, ensure paths are in UNIX format before anything is touched\nif $mingw; then\n  [ -n \"$JAVA_HOME\" ] && [ -d \"$JAVA_HOME\" ] \\\n    && JAVA_HOME=\"$(\n      cd \"$JAVA_HOME\" || (\n        echo \"cannot cd into $JAVA_HOME.\" >&2\n        exit 1\n      )\n      pwd\n    )\"\nfi\n\nif [ -z \"$JAVA_HOME\" ]; then\n  javaExecutable=\"$(which javac)\"\n  if [ -n \"$javaExecutable\" ] && ! [ \"$(expr \"$javaExecutable\" : '\\([^ ]*\\)')\" = \"no\" ]; then\n    # readlink(1) is not available as standard on Solaris 10.\n    readLink=$(which readlink)\n    if [ ! \"$(expr \"$readLink\" : '\\([^ ]*\\)')\" = \"no\" ]; then\n      if $darwin; then\n        javaHome=\"$(dirname \"$javaExecutable\")\"\n        javaExecutable=\"$(cd \"$javaHome\" && pwd -P)/javac\"\n      else\n        javaExecutable=\"$(readlink -f \"$javaExecutable\")\"\n      fi\n      javaHome=\"$(dirname \"$javaExecutable\")\"\n      javaHome=$(expr \"$javaHome\" : '\\(.*\\)/bin')\n      JAVA_HOME=\"$javaHome\"\n      export JAVA_HOME\n    fi\n  fi\nfi\n\nif [ -z \"$JAVACMD\" ]; then\n  if [ -n \"$JAVA_HOME\" ]; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ]; then\n      # IBM's JDK on AIX uses strange locations for the executables\n      JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n      JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n  else\n    JAVACMD=\"$(\n      \\unset -f command 2>/dev/null\n      \\command -v java\n    )\"\n  fi\nfi\n\nif [ ! -x \"$JAVACMD\" ]; then\n  echo \"Error: JAVA_HOME is not defined correctly.\" >&2\n  echo \"  We cannot execute $JAVACMD\" >&2\n  exit 1\nfi\n\nif [ -z \"$JAVA_HOME\" ]; then\n  echo \"Warning: JAVA_HOME environment variable is not set.\" >&2\nfi\n\n# traverses directory structure from process work directory to filesystem root\n# first directory with .mvn subdirectory is considered project base directory\nfind_maven_basedir() {\n  if [ -z \"$1\" ]; then\n    echo \"Path not specified to find_maven_basedir\" >&2\n    return 1\n  fi\n\n  basedir=\"$1\"\n  wdir=\"$1\"\n  while [ \"$wdir\" != '/' ]; do\n    if [ -d \"$wdir\"/.mvn ]; then\n      basedir=$wdir\n      break\n    fi\n    # workaround for JBEAP-8937 (on Solaris 10/Sparc)\n    if [ -d \"${wdir}\" ]; then\n      wdir=$(\n        cd \"$wdir/..\" || exit 1\n        pwd\n      )\n    fi\n    # end of workaround\n  done\n  printf '%s' \"$(\n    cd \"$basedir\" || exit 1\n    pwd\n  )\"\n}\n\n# concatenates all lines of a file\nconcat_lines() {\n  if [ -f \"$1\" ]; then\n    # Remove \\r in case we run on Windows within Git Bash\n    # and check out the repository with auto CRLF management\n    # enabled. Otherwise, we may read lines that are delimited with\n    # \\r\\n and produce $'-Xarg\\r' rather than -Xarg due to word\n    # splitting rules.\n    tr -s '\\r\\n' ' ' <\"$1\"\n  fi\n}\n\nlog() {\n  if [ \"$MVNW_VERBOSE\" = true ]; then\n    printf '%s\\n' \"$1\"\n  fi\n}\n\nBASE_DIR=$(find_maven_basedir \"$(dirname \"$0\")\")\nif [ -z \"$BASE_DIR\" ]; then\n  exit 1\nfi\n\nMAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-\"$BASE_DIR\"}\nexport MAVEN_PROJECTBASEDIR\nlog \"$MAVEN_PROJECTBASEDIR\"\n\ntrim() {\n  # MWRAPPER-139:\n  #   Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.\n  #   Needed for removing poorly interpreted newline sequences when running in more\n  #   exotic environments such as mingw bash on Windows.\n  printf \"%s\" \"${1}\" | tr -d '[:space:]'\n}\n\n##########################################################################################\n# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central\n# This allows using the maven wrapper in projects that prohibit checking in binary data.\n##########################################################################################\nwrapperJarPath=\"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar\"\nif [ -r \"$wrapperJarPath\" ]; then\n  log \"Found $wrapperJarPath\"\nelse\n  log \"Couldn't find $wrapperJarPath, downloading it ...\"\n\n  if [ -n \"$MVNW_REPOURL\" ]; then\n    wrapperUrl=\"$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar\"\n  else\n    wrapperUrl=\"https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar\"\n  fi\n  while IFS=\"=\" read -r key value; do\n    case \"$key\" in wrapperUrl)\n      wrapperUrl=$(trim \"${value-}\")\n      break\n      ;;\n    esac\n  done <\"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties\"\n  log \"Downloading from: $wrapperUrl\"\n\n  if $cygwin; then\n    wrapperJarPath=$(cygpath --path --windows \"$wrapperJarPath\")\n  fi\n\n  if command -v wget >/dev/null; then\n    log \"Found wget ... using wget\"\n    [ \"$MVNW_VERBOSE\" = true ] && QUIET=\"\" || QUIET=\"--quiet\"\n    if [ -z \"$MVNW_USERNAME\" ] || [ -z \"$MVNW_PASSWORD\" ]; then\n      wget ${QUIET:+\"$QUIET\"} \"$wrapperUrl\" -O \"$wrapperJarPath\" || rm -f \"$wrapperJarPath\"\n    else\n      wget ${QUIET:+\"$QUIET\"} --http-user=\"$MVNW_USERNAME\" --http-password=\"$MVNW_PASSWORD\" \"$wrapperUrl\" -O \"$wrapperJarPath\" || rm -f \"$wrapperJarPath\"\n    fi\n  elif command -v curl >/dev/null; then\n    log \"Found curl ... using curl\"\n    [ \"$MVNW_VERBOSE\" = true ] && QUIET=\"\" || QUIET=\"--silent\"\n    if [ -z \"$MVNW_USERNAME\" ] || [ -z \"$MVNW_PASSWORD\" ]; then\n      curl ${QUIET:+\"$QUIET\"} -o \"$wrapperJarPath\" \"$wrapperUrl\" -f -L || rm -f \"$wrapperJarPath\"\n    else\n      curl ${QUIET:+\"$QUIET\"} --user \"$MVNW_USERNAME:$MVNW_PASSWORD\" -o \"$wrapperJarPath\" \"$wrapperUrl\" -f -L || rm -f \"$wrapperJarPath\"\n    fi\n  else\n    log \"Falling back to using Java to download\"\n    javaSource=\"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java\"\n    javaClass=\"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class\"\n    # For Cygwin, switch paths to Windows format before running javac\n    if $cygwin; then\n      javaSource=$(cygpath --path --windows \"$javaSource\")\n      javaClass=$(cygpath --path --windows \"$javaClass\")\n    fi\n    if [ -e \"$javaSource\" ]; then\n      if [ ! -e \"$javaClass\" ]; then\n        log \" - Compiling MavenWrapperDownloader.java ...\"\n        (\"$JAVA_HOME/bin/javac\" \"$javaSource\")\n      fi\n      if [ -e \"$javaClass\" ]; then\n        log \" - Running MavenWrapperDownloader.java ...\"\n        (\"$JAVA_HOME/bin/java\" -cp .mvn/wrapper MavenWrapperDownloader \"$wrapperUrl\" \"$wrapperJarPath\") || rm -f \"$wrapperJarPath\"\n      fi\n    fi\n  fi\nfi\n##########################################################################################\n# End of extension\n##########################################################################################\n\n# If specified, validate the SHA-256 sum of the Maven wrapper jar file\nwrapperSha256Sum=\"\"\nwhile IFS=\"=\" read -r key value; do\n  case \"$key\" in wrapperSha256Sum)\n    wrapperSha256Sum=$(trim \"${value-}\")\n    break\n    ;;\n  esac\ndone <\"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties\"\nif [ -n \"$wrapperSha256Sum\" ]; then\n  wrapperSha256Result=false\n  if command -v sha256sum >/dev/null; then\n    if echo \"$wrapperSha256Sum  $wrapperJarPath\" | sha256sum -c - >/dev/null 2>&1; then\n      wrapperSha256Result=true\n    fi\n  elif command -v shasum >/dev/null; then\n    if echo \"$wrapperSha256Sum  $wrapperJarPath\" | shasum -a 256 -c >/dev/null 2>&1; then\n      wrapperSha256Result=true\n    fi\n  else\n    echo \"Checksum validation was requested but neither 'sha256sum' or 'shasum' are available.\" >&2\n    echo \"Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties.\" >&2\n    exit 1\n  fi\n  if [ $wrapperSha256Result = false ]; then\n    echo \"Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.\" >&2\n    echo \"Investigate or delete $wrapperJarPath to attempt a clean download.\" >&2\n    echo \"If you updated your Maven version, you need to update the specified wrapperSha256Sum property.\" >&2\n    exit 1\n  fi\nfi\n\nMAVEN_OPTS=\"$(concat_lines \"$MAVEN_PROJECTBASEDIR/.mvn/jvm.config\") $MAVEN_OPTS\"\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin; then\n  [ -n \"$JAVA_HOME\" ] \\\n    && JAVA_HOME=$(cygpath --path --windows \"$JAVA_HOME\")\n  [ -n \"$CLASSPATH\" ] \\\n    && CLASSPATH=$(cygpath --path --windows \"$CLASSPATH\")\n  [ -n \"$MAVEN_PROJECTBASEDIR\" ] \\\n    && MAVEN_PROJECTBASEDIR=$(cygpath --path --windows \"$MAVEN_PROJECTBASEDIR\")\nfi\n\n# Provide a \"standardized\" way to retrieve the CLI args that will\n# work with both Windows and non-Windows executions.\nMAVEN_CMD_LINE_ARGS=\"$MAVEN_CONFIG $*\"\nexport MAVEN_CMD_LINE_ARGS\n\nWRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain\n\n# shellcheck disable=SC2086 # safe args\nexec \"$JAVACMD\" \\\n  $MAVEN_OPTS \\\n  $MAVEN_DEBUG_OPTS \\\n  -classpath \"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar\" \\\n  \"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}\" \\\n  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG \"$@\"\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/wrapper-maven/mvnw.cmd",
    "content": "@REM ----------------------------------------------------------------------------\r\n@REM Licensed to the Apache Software Foundation (ASF) under one\r\n@REM or more contributor license agreements.  See the NOTICE file\r\n@REM distributed with this work for additional information\r\n@REM regarding copyright ownership.  The ASF licenses this file\r\n@REM to you under the Apache License, Version 2.0 (the\r\n@REM \"License\"); you may not use this file except in compliance\r\n@REM with the License.  You may obtain a copy of the License at\r\n@REM\r\n@REM    http://www.apache.org/licenses/LICENSE-2.0\r\n@REM\r\n@REM Unless required by applicable law or agreed to in writing,\r\n@REM software distributed under the License is distributed on an\r\n@REM \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\r\n@REM KIND, either express or implied.  See the License for the\r\n@REM specific language governing permissions and limitations\r\n@REM under the License.\r\n@REM ----------------------------------------------------------------------------\r\n\r\n@REM ----------------------------------------------------------------------------\r\n@REM Apache Maven Wrapper startup batch script, version 3.3.4\r\n@REM\r\n@REM Required ENV vars:\r\n@REM JAVA_HOME - location of a JDK home dir\r\n@REM\r\n@REM Optional ENV vars\r\n@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands\r\n@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending\r\n@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven\r\n@REM     e.g. to debug Maven itself, use\r\n@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000\r\n@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files\r\n@REM ----------------------------------------------------------------------------\r\n\r\n@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'\r\n@echo off\r\n@REM set title of command window\r\ntitle %0\r\n@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'\r\n@if \"%MAVEN_BATCH_ECHO%\" == \"on\"  echo %MAVEN_BATCH_ECHO%\r\n\r\n@REM set %HOME% to equivalent of $HOME\r\nif \"%HOME%\" == \"\" (set \"HOME=%HOMEDRIVE%%HOMEPATH%\")\r\n\r\n@REM Execute a user defined script before this one\r\nif not \"%MAVEN_SKIP_RC%\" == \"\" goto skipRcPre\r\n@REM check for pre script, once with legacy .bat ending and once with .cmd ending\r\nif exist \"%USERPROFILE%\\mavenrc_pre.bat\" call \"%USERPROFILE%\\mavenrc_pre.bat\" %*\r\nif exist \"%USERPROFILE%\\mavenrc_pre.cmd\" call \"%USERPROFILE%\\mavenrc_pre.cmd\" %*\r\n:skipRcPre\r\n\r\n@setlocal\r\n\r\nset ERROR_CODE=0\r\n\r\n@REM To isolate internal variables from possible post scripts, we use another setlocal\r\n@setlocal\r\n\r\n@REM ==== START VALIDATION ====\r\nif not \"%JAVA_HOME%\" == \"\" goto OkJHome\r\n\r\necho. >&2\r\necho Error: JAVA_HOME not found in your environment. >&2\r\necho Please set the JAVA_HOME variable in your environment to match the >&2\r\necho location of your Java installation. >&2\r\necho. >&2\r\ngoto error\r\n\r\n:OkJHome\r\nif exist \"%JAVA_HOME%\\bin\\java.exe\" goto init\r\n\r\necho. >&2\r\necho Error: JAVA_HOME is set to an invalid directory. >&2\r\necho JAVA_HOME = \"%JAVA_HOME%\" >&2\r\necho Please set the JAVA_HOME variable in your environment to match the >&2\r\necho location of your Java installation. >&2\r\necho. >&2\r\ngoto error\r\n\r\n@REM ==== END VALIDATION ====\r\n\r\n:init\r\n\r\n@REM Find the project base dir, i.e. the directory that contains the folder \".mvn\".\r\n@REM Fallback to current working directory if not found.\r\n\r\nset MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%\r\nIF NOT \"%MAVEN_PROJECTBASEDIR%\"==\"\" goto endDetectBaseDir\r\n\r\nset EXEC_DIR=%CD%\r\nset WDIR=%EXEC_DIR%\r\n:findBaseDir\r\nIF EXIST \"%WDIR%\"\\.mvn goto baseDirFound\r\ncd ..\r\nIF \"%WDIR%\"==\"%CD%\" goto baseDirNotFound\r\nset WDIR=%CD%\r\ngoto findBaseDir\r\n\r\n:baseDirFound\r\nset MAVEN_PROJECTBASEDIR=%WDIR%\r\ncd \"%EXEC_DIR%\"\r\ngoto endDetectBaseDir\r\n\r\n:baseDirNotFound\r\nset MAVEN_PROJECTBASEDIR=%EXEC_DIR%\r\ncd \"%EXEC_DIR%\"\r\n\r\n:endDetectBaseDir\r\n\r\nIF NOT EXIST \"%MAVEN_PROJECTBASEDIR%\\.mvn\\jvm.config\" goto endReadAdditionalConfig\r\n\r\n@setlocal EnableExtensions EnableDelayedExpansion\r\nfor /F \"usebackq delims=\" %%a in (\"%MAVEN_PROJECTBASEDIR%\\.mvn\\jvm.config\") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a\r\n@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%\r\n\r\n:endReadAdditionalConfig\r\n\r\nSET MAVEN_JAVA_EXE=\"%JAVA_HOME%\\bin\\java.exe\"\r\nset WRAPPER_JAR=\"%MAVEN_PROJECTBASEDIR%\\.mvn\\wrapper\\maven-wrapper.jar\"\r\nset WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain\r\n\r\nset WRAPPER_URL=\"https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar\"\r\n\r\nFOR /F \"usebackq tokens=1,2 delims==\" %%A IN (\"%MAVEN_PROJECTBASEDIR%\\.mvn\\wrapper\\maven-wrapper.properties\") DO (\r\n    IF \"%%A\"==\"wrapperUrl\" SET WRAPPER_URL=%%B\r\n)\r\n\r\n@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central\r\n@REM This allows using the maven wrapper in projects that prohibit checking in binary data.\r\nif exist %WRAPPER_JAR% (\r\n    if \"%MVNW_VERBOSE%\" == \"true\" (\r\n        echo Found %WRAPPER_JAR%\r\n    )\r\n) else (\r\n    if not \"%MVNW_REPOURL%\" == \"\" (\r\n        SET WRAPPER_URL=\"%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar\"\r\n    )\r\n    if \"%MVNW_VERBOSE%\" == \"true\" (\r\n        echo Couldn't find %WRAPPER_JAR%, downloading it ...\r\n        echo Downloading from: %WRAPPER_URL%\r\n    )\r\n\r\n    powershell -Command \"&{\"^\r\n\t\t\"$webclient = new-object System.Net.WebClient;\"^\r\n\t\t\"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {\"^\r\n\t\t\"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');\"^\r\n\t\t\"}\"^\r\n\t\t\"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')\"^\r\n\t\t\"}\"\r\n    if \"%MVNW_VERBOSE%\" == \"true\" (\r\n        echo Finished downloading %WRAPPER_JAR%\r\n    )\r\n)\r\n@REM End of extension\r\n\r\n@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file\r\nSET WRAPPER_SHA_256_SUM=\"\"\r\nFOR /F \"usebackq tokens=1,2 delims==\" %%A IN (\"%MAVEN_PROJECTBASEDIR%\\.mvn\\wrapper\\maven-wrapper.properties\") DO (\r\n    IF \"%%A\"==\"wrapperSha256Sum\" SET WRAPPER_SHA_256_SUM=%%B\r\n)\r\nIF NOT %WRAPPER_SHA_256_SUM%==\"\" (\r\n    powershell -Command \"&{\"^\r\n       \"Import-Module $PSHOME\\Modules\\Microsoft.PowerShell.Utility -Function Get-FileHash;\"^\r\n       \"$hash = (Get-FileHash \\\"%WRAPPER_JAR%\\\" -Algorithm SHA256).Hash.ToLower();\"^\r\n       \"If('%WRAPPER_SHA_256_SUM%' -ne $hash){\"^\r\n       \"  Write-Error 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';\"^\r\n       \"  Write-Error 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';\"^\r\n       \"  Write-Error 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';\"^\r\n       \"  exit 1;\"^\r\n       \"}\"^\r\n       \"}\"\r\n    if ERRORLEVEL 1 goto error\r\n)\r\n\r\n@REM Provide a \"standardized\" way to retrieve the CLI args that will\r\n@REM work with both Windows and non-Windows executions.\r\nset MAVEN_CMD_LINE_ARGS=%*\r\n\r\n%MAVEN_JAVA_EXE% ^\r\n  %JVM_CONFIG_MAVEN_PROPS% ^\r\n  %MAVEN_OPTS% ^\r\n  %MAVEN_DEBUG_OPTS% ^\r\n  -classpath %WRAPPER_JAR% ^\r\n  \"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%\" ^\r\n  %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*\r\nif ERRORLEVEL 1 goto error\r\ngoto end\r\n\r\n:error\r\nset ERROR_CODE=1\r\n\r\n:end\r\n@endlocal & set ERROR_CODE=%ERROR_CODE%\r\n\r\nif not \"%MAVEN_SKIP_RC%\"==\"\" goto skipRcPost\r\n@REM check for post script, once with legacy .bat ending and once with .cmd ending\r\nif exist \"%USERPROFILE%\\mavenrc_post.bat\" call \"%USERPROFILE%\\mavenrc_post.bat\"\r\nif exist \"%USERPROFILE%\\mavenrc_post.cmd\" call \"%USERPROFILE%\\mavenrc_post.cmd\"\r\n:skipRcPost\r\n\r\n@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'\r\nif \"%MAVEN_BATCH_PAUSE%\"==\"on\" pause\r\n\r\nif \"%MAVEN_TERMINATE_CMD%\"==\"on\" exit %ERROR_CODE%\r\n\r\ncmd /C exit /B %ERROR_CODE%\r\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/wrapper-maven/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<groupId>MyAssetContract</groupId>\n\t<artifactId>MyAssetContract</artifactId>\n\t<version>1.0-SNAPSHOT</version>\n\t<properties>\n\n\t\t<!-- Generic properties -->\n\t\t<java.version>11</java.version>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>\n\n\t\t<!-- fabric-chaincode-java -->\n\t\t<fabric-chaincode-java.version>2.5.9</fabric-chaincode-java.version>\n\n\t</properties>\n\t\n    <repositories>\n        <repository>\n            <id>jitpack.io</id>\n            <url>https://www.jitpack.io</url>\n        </repository>\n\t\t<repository>\n            <id>artifactory</id>\n            <url>https://hyperledger.jfrog.io/hyperledger/fabric-maven</url>\n        </repository>\t\t\n\t\t<repository>\n\t\t\t<id>localfabric</id>\n\t\t\t<url>file://${project.basedir}/repository</url>\n\t\t</repository>\n    </repositories>\n\n\t<dependencies>\n\n\t\t<!-- fabric-chaincode-java -->\n\t\t<dependency>\n\t\t\t<groupId>org.hyperledger.fabric-chaincode-java</groupId>\n\t\t\t<artifactId>fabric-chaincode-shim</artifactId>\n\t\t\t<version>${fabric-chaincode-java.version}</version>\n\t\t\t<scope>compile</scope>\n\t\t</dependency>\n\n\t</dependencies>\n\t<build>\n\t\t<sourceDirectory>src</sourceDirectory>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t<version>3.15.0</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<release>${java.version}</release>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-shade-plugin</artifactId>\n\t\t\t\t<version>3.6.2</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>shade</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<finalName>chaincode</finalName>\n\t\t\t\t\t\t\t<transformers>\n\t\t\t\t\t\t\t\t<transformer implementation=\"org.apache.maven.plugins.shade.resource.ServicesResourceTransformer\"/>\n\t\t\t\t\t\t\t\t<transformer implementation=\"org.apache.maven.plugins.shade.resource.ManifestResourceTransformer\">\n\t\t\t\t\t\t\t\t\t<mainClass>org.hyperledger.fabric.contract.ContractRouter</mainClass>\n\t\t\t\t\t\t\t\t</transformer>\n\t\t\t\t\t\t\t</transformers>\n\t\t\t\t\t\t\t<filters>\n\t\t\t\t\t\t\t\t<filter>\n\t\t\t\t\t\t\t\t\t<!-- filter out signature files from signed dependencies, else repackaging fails with security ex -->\n\t\t\t\t\t\t\t\t\t<artifact>*:*</artifact>\n\t\t\t\t\t\t\t\t\t<excludes>\n\t\t\t\t\t\t\t\t\t\t<exclude>META-INF/*.SF</exclude>\n\t\t\t\t\t\t\t\t\t\t<exclude>META-INF/*.DSA</exclude>\n\t\t\t\t\t\t\t\t\t\t<exclude>META-INF/*.RSA</exclude>\n\t\t\t\t\t\t\t\t\t</excludes>\n\t\t\t\t\t\t\t\t</filter>\n\t\t\t\t\t\t\t</filters>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/wrapper-maven/src/main/java/org/hyperledger/fabric/example/WrapperMaven.java",
    "content": "/*\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.example;\n\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.annotation.Contact;\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.Default;\nimport org.hyperledger.fabric.contract.annotation.Info;\nimport org.hyperledger.fabric.contract.annotation.License;\nimport org.hyperledger.fabric.contract.annotation.Transaction;\n\n@Contract(name = \"WrapperMaven\",\n    info = @Info(title = \"BareGradle contract\",\n                description = \"Contract but using all the APIs\",\n                version = \"0.0.1\",\n                license =\n                        @License(name = \"SPDX-License-Identifier: Apache-2.0\",\n                                url = \"\"),\n                                contact =  @Contact(email = \"fred@example.com\",\n                                                name = \"fred\",\n                                                url = \"http://fred.example.com\")))\n@Default\npublic class WrapperMaven implements ContractInterface {\n    public WrapperMaven() {\n\n    }\n\n    @Transaction()\n    public String whoami(Context ctx){\n       return this.getClass().getSimpleName();\n    }\n}"
  },
  {
    "path": "fabric-chaincode-integration-test/src/contracts/wrapper-maven/src/main/resources/config.props",
    "content": "MAX_INBOUND_MESSAGE_SIZE=4000\nCHAINCODE_METRICS_ENABLED=true\nTP_CORE_POOL_SIZE=4\nTP_MAX_POOL_SIZE=4\nTP_QUEUE_SIZE=4000\n "
  },
  {
    "path": "fabric-chaincode-integration-test/src/test/java/org/hyperleder/fabric/shim/integration/contractinstall/ContractInstallTest.java",
    "content": "/*\nCopyright IBM Corp. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\npackage org.hyperleder.fabric.shim.integration.contractinstall;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.core.StringContains.containsString;\n\nimport org.hyperleder.fabric.shim.integration.util.FabricState;\nimport org.hyperleder.fabric.shim.integration.util.InvokeHelper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\n/** Basic Java Chaincode Test */\npublic class ContractInstallTest {\n\n    @BeforeAll\n    public static void setUp() throws Exception {\n        FabricState.getState().start();\n    }\n\n    @Test\n    public void testInstall() {\n\n        InvokeHelper helper = InvokeHelper.newHelper(\"baregradlecc\", \"sachannel\");\n        String text = helper.invoke(\"org1\", \"whoami\");\n        assertThat(text, containsString(\"BareGradle\"));\n\n        helper = InvokeHelper.newHelper(\"baremaven\", \"sachannel\");\n        text = helper.invoke(\"org1\", \"whoami\");\n        assertThat(text, containsString(\"BareMaven\"));\n\n        helper = InvokeHelper.newHelper(\"wrappermaven\", \"sachannel\");\n        text = helper.invoke(\"org1\", \"whoami\");\n        assertThat(text, containsString(\"WrapperMaven\"));\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/test/java/org/hyperleder/fabric/shim/integration/ledgertests/LedgerIntegrationTest.java",
    "content": "/*\nCopyright IBM Corp. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\npackage org.hyperleder.fabric.shim.integration.ledgertests;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.core.StringContains.containsString;\n\nimport org.hyperleder.fabric.shim.integration.util.FabricState;\nimport org.hyperleder.fabric.shim.integration.util.InvokeHelper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\n/** Basic Java Chaincode Test */\npublic class LedgerIntegrationTest {\n\n    @BeforeAll\n    public static void setUp() throws Exception {\n\n        FabricState.getState().start();\n    }\n\n    @Test\n    public void testLedgers() {\n        InvokeHelper helper = InvokeHelper.newHelper(\"ledgercc\", \"sachannel\");\n\n        String text = helper.invoke(\"org1\", \"accessLedgers\");\n        assertThat(text, containsString(\"success\"));\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/test/java/org/hyperleder/fabric/shim/integration/shimtests/SACCIntegrationTest.java",
    "content": "/*\nCopyright IBM Corp. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\npackage org.hyperleder.fabric.shim.integration.shimtests;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.core.StringContains.containsString;\n\nimport org.hyperleder.fabric.shim.integration.util.FabricState;\nimport org.hyperleder.fabric.shim.integration.util.InvokeHelper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\n/** Basic Java Chaincode Test */\npublic class SACCIntegrationTest {\n\n    @BeforeAll\n    public static void setUp() throws Exception {\n        FabricState.getState().start();\n    }\n\n    @Test\n    public void testLedger() {\n\n        InvokeHelper helper = InvokeHelper.newHelper(\"shimcc\", \"sachannel\");\n        String text = helper.invoke(\"org1\", \"putBulkStates\");\n        assertThat(text, containsString(\"success\"));\n\n        text = helper.invoke(\"org1\", \"getByRange\", \"key120\", \"key170\");\n        assertThat(text, containsString(\"50\"));\n\n        text = helper.invoke(\"org1\", \"getByRangePaged\", \"key120\", \"key170\", \"10\", \"\");\n        System.out.println(text);\n        assertThat(text, containsString(\"key130\"));\n\n        text = helper.invoke(\"org1\", \"getMetricsProviderName\");\n        System.out.println(text);\n        assertThat(text, containsString(\"org.hyperledger.fabric.metrics.impl.DefaultProvider\"));\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/test/java/org/hyperleder/fabric/shim/integration/shimtests/SBECCIntegrationTest.java",
    "content": "/*\nCopyright IBM Corp. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\npackage org.hyperleder.fabric.shim.integration.shimtests;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.not;\nimport static org.hamcrest.core.StringContains.containsString;\n\nimport org.hyperleder.fabric.shim.integration.util.FabricState;\nimport org.hyperleder.fabric.shim.integration.util.InvokeHelper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\npublic class SBECCIntegrationTest {\n\n    @BeforeAll\n    public static void setUp() throws Exception {\n        FabricState.getState().start();\n    }\n\n    @Test\n    public void runSBE_pub_setget() {\n        final String mode = \"pub\";\n\n        final InvokeHelper helper = InvokeHelper.newHelper(\"shimcc\", \"sachannel\");\n\n        String text;\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:setval\", mode, \"foo\");\n        assertThat(text, containsString(\"success\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:getval\", mode);\n        assertThat(text, containsString(\"foo\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:addorgs\", mode, \"org1MSP\");\n        assertThat(text, containsString(\"success\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:listorgs\", mode);\n        assertThat(text, containsString(\"org1MSP\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:setval\", mode, \"val1\");\n        assertThat(text, containsString(\"success\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:getval\", mode);\n        assertThat(text, containsString(\"val1\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:setval\", mode, \"val2\");\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:getval\", mode);\n        assertThat(text, containsString(\"val2\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:addorgs\", mode, \"org2MSP\");\n        assertThat(text, containsString(\"success\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:listorgs\", mode);\n        assertThat(text, containsString(\"org2MSP\"));\n        assertThat(text, containsString(\"org1MSP\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:setval\", mode, \"val3\");\n        assertThat(text, containsString(\"success\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:getval\", mode);\n        assertThat(text, containsString(\"val3\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:setval\", mode, \"val4\");\n        assertThat(text, containsString(\"success\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:getval\", mode);\n        assertThat(text, containsString(\"val4\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:delorgs\", mode, \"org1MSP\");\n        assertThat(text, containsString(\"success\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:listorgs\", mode);\n        assertThat(text, containsString(\"org2MSP\"));\n        assertThat(text, not(containsString(\"org1MSP\")));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:deleteval\", mode);\n        assertThat(text, containsString(\"success\"));\n        text = helper.invoke(\"org1\", \"EndorsementCC:recordExists\", mode);\n        assertThat(text, containsString(\"false\"));\n    }\n\n    @Test\n    public void runSBE_priv() {\n        final String mode = \"priv\";\n\n        final InvokeHelper helper = InvokeHelper.newHelper(\"shimcc\", \"sachannel\");\n\n        String text;\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:setval\", mode, \"foo\");\n        assertThat(text, containsString(\"success\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:getval\", mode);\n        assertThat(text, containsString(\"foo\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:addorgs\", mode, \"org1MSP\");\n        assertThat(text, containsString(\"success\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:listorgs\", mode);\n        assertThat(text, containsString(\"org1MSP\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:setval\", mode, \"val1\");\n        assertThat(text, containsString(\"success\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:getval\", mode);\n        assertThat(text, containsString(\"val1\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:setval\", mode, \"val2\");\n        assertThat(text, containsString(\"success\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:getval\", mode);\n        assertThat(text, containsString(\"val2\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:addorgs\", mode, \"org2MSP\");\n        assertThat(text, containsString(\"success\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:listorgs\", mode);\n        assertThat(text, containsString(\"org2MSP\"));\n        assertThat(text, containsString(\"org1MSP\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:setval\", mode, \"val3\");\n        assertThat(text, containsString(\"success\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:getval\", mode);\n        assertThat(text, containsString(\"val3\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:setval\", mode, \"val4\");\n        assertThat(text, containsString(\"success\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:getval\", mode);\n        assertThat(text, containsString(\"val4\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:delorgs\", mode, \"org1MSP\");\n        assertThat(text, containsString(\"success\"));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:listorgs\", mode);\n        assertThat(text, containsString(\"org2MSP\"));\n        assertThat(text, not(containsString(\"org1MSP\")));\n\n        text = helper.invoke(\"org1\", \"EndorsementCC:deleteval\", mode);\n        assertThat(text, containsString(\"success\"));\n        text = helper.invoke(\"org1\", \"EndorsementCC:recordExists\", mode);\n        assertThat(text, containsString(\"false\"));\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/test/java/org/hyperleder/fabric/shim/integration/util/Bash.java",
    "content": "/*\nCopyright IBM Corp. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\npackage org.hyperleder.fabric.shim.integration.util;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\n\n/** Represents the 'peer' cli command */\npublic final class Bash extends Command {\n\n    public static BashBuilder newBuilder() {\n        return new BashBuilder();\n    }\n\n    public static class BashBuilder extends Command.Builder<Bash> {\n        String cmd;\n        String orderer;\n        String channel;\n        String ccname;\n        boolean evaluate = false;\n        int waitForEventTimeout;\n        List<String> args = new ArrayList<String>();\n        Map<String, String> transientData;\n\n        public BashBuilder duplicate() {\n            try {\n                return (BashBuilder) this.clone();\n            } catch (CloneNotSupportedException e) {\n\n                e.printStackTrace();\n                return null;\n            }\n        }\n\n        public BashBuilder cmd(String cmd) {\n            this.cmd = cmd;\n            return this;\n        }\n\n        public BashBuilder cmdargs(String argsArray[]) {\n            this.args = Arrays.asList(argsArray);\n            return this;\n        }\n\n        public Bash build(Map<String, String> additionalEnv) {\n\n            ArrayList<String> list = new ArrayList<>();\n            list.add(cmd);\n\n            return new Bash(list, additionalEnv);\n        }\n\n        public Bash build() {\n\n            ArrayList<String> list = new ArrayList<>();\n            list.add(cmd);\n            list.addAll(args);\n\n            return new Bash(list);\n        }\n    }\n\n    Bash(List<String> cmd) {\n        super(cmd);\n    }\n\n    Bash(List<String> cmd, Map<String, String> env) {\n        super(cmd, env);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/test/java/org/hyperleder/fabric/shim/integration/util/Command.java",
    "content": "/*\nCopyright IBM Corp. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage org.hyperleder.fabric.shim.integration.util;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.PrintStream;\nimport java.lang.ProcessBuilder.Redirect;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.CompletableFuture;\nimport java.util.concurrent.ExecutionException;\n\npublic class Command {\n\n    protected final List<String> cmd;\n    protected final Map<String, String> env = new HashMap<>();\n\n    Command(List<String> cmd, Map<String, String> additionalEnv) {\n        this.cmd = cmd;\n        this.env.putAll(additionalEnv);\n    }\n\n    Command(List<String> cmd) {\n        this(cmd, Collections.emptyMap());\n    }\n\n    public static final class Result {\n        public List<String> stdout;\n        public List<String> stderr;\n        public int exitcode;\n    }\n\n    /** Run but don't suppress the output being printed directly */\n    public Result run() {\n        return this.run(false);\n    }\n\n    /**\n     * Run the command, and process the output to arrays for later parsing and checking\n     *\n     * @param quiet true if the output should NOT be printed directly to System.out/System.err\n     */\n    public Result run(boolean quiet) {\n\n        ProcessBuilder processBuilder = new ProcessBuilder(cmd);\n        processBuilder.environment().putAll(env);\n        final Result result = new Result();\n\n        System.out.println(\"Running:\" + this);\n        try {\n\n            processBuilder.redirectInput(Redirect.INHERIT);\n            processBuilder.redirectErrorStream(true);\n\n            Process process = processBuilder.start();\n            System.out.println(\"Started..... \");\n\n            CompletableFuture<ArrayList<String>> soutFut =\n                    readOutStream(process.getInputStream(), quiet ? null : System.out);\n            CompletableFuture<ArrayList<String>> serrFut =\n                    readOutStream(process.getErrorStream(), quiet ? null : System.err);\n\n            CompletableFuture<Result> resultFut = soutFut.thenCombine(serrFut, (stdout, stderr) -> {\n                // print to current stderr the stderr of process and return the stdout\n                result.stderr = stderr;\n                result.stdout = stdout;\n                return result;\n            });\n\n            result.exitcode = process.waitFor();\n            // get stdout once ready, blocking\n            resultFut.get();\n\n        } catch (IOException | InterruptedException | ExecutionException e) {\n            e.printStackTrace();\n            result.exitcode = -1;\n        }\n\n        return result;\n    }\n\n    /**\n     * Collect the information from the executed process and add them to a result object\n     *\n     * @param is\n     * @param stream\n     * @return Completable Future with the array list of the stdout/stderr\n     */\n    CompletableFuture<ArrayList<String>> readOutStream(InputStream is, PrintStream stream) {\n        return CompletableFuture.supplyAsync(() -> {\n            try (InputStreamReader isr = new InputStreamReader(is);\n                    BufferedReader br = new BufferedReader(isr); ) {\n                ArrayList<String> res = new ArrayList<>();\n                String inputLine;\n                while ((inputLine = br.readLine()) != null) {\n                    if (stream != null) stream.println(inputLine);\n                    res.add(inputLine);\n                }\n                return res;\n            } catch (Throwable e) {\n                throw new RuntimeException(\"problem with executing program\", e);\n            }\n        });\n    }\n\n    public String toString() {\n        return \"[\" + String.join(\" \", cmd) + \"]\";\n    }\n\n    public static class Builder<T extends Command> implements Cloneable {\n        @SuppressWarnings(\"unchecked\")\n        public Builder<T> duplicate() {\n            try {\n                return (Builder<T>) this.clone();\n            } catch (CloneNotSupportedException e) {\n                e.printStackTrace();\n                return null;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/test/java/org/hyperleder/fabric/shim/integration/util/Docker.java",
    "content": "/*\nCopyright IBM Corp. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\npackage org.hyperleder.fabric.shim.integration.util;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/** Represents the 'docker' cli command */\npublic final class Docker extends Command {\n\n    public static DockerBuilder newBuilder() {\n        return new DockerBuilder();\n    }\n\n    public static final class DockerBuilder implements Cloneable {\n        boolean exec;\n        String container;\n        String script;\n        String channel;\n\n        public DockerBuilder duplicate() {\n            try {\n                return (DockerBuilder) this.clone();\n            } catch (CloneNotSupportedException e) {\n                e.printStackTrace();\n                return null;\n            }\n        }\n\n        public DockerBuilder script(String script) {\n            this.script = script;\n            return this;\n        }\n\n        public DockerBuilder channel(String channel) {\n            this.channel = channel;\n            return this;\n        }\n\n        public DockerBuilder container(String container) {\n            this.container = container;\n            return this;\n        }\n\n        public DockerBuilder exec() {\n            this.exec = true;\n            return this;\n        }\n\n        public Docker build() {\n\n            ArrayList<String> list = new ArrayList<>();\n            list.add(\"docker\");\n            if (exec) {\n                list.add(\"exec\");\n            }\n\n            if (container == null || container.isEmpty()) {\n                throw new RuntimeException(\"container should be set\");\n            }\n            list.add(container);\n\n            if (script == null || script.isEmpty()) {\n                throw new RuntimeException(\"script should be set\");\n            }\n            list.add(script);\n\n            if (channel == null || channel.isEmpty()) {\n                throw new RuntimeException(\"channel should be set\");\n            }\n            list.add(channel);\n\n            return new Docker(list);\n        }\n    }\n\n    Docker(List<String> cmd) {\n        super(cmd);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/test/java/org/hyperleder/fabric/shim/integration/util/DockerCompose.java",
    "content": "/*\nCopyright IBM Corp. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\npackage org.hyperleder.fabric.shim.integration.util;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/** Represents the 'peer' cli command */\npublic final class DockerCompose extends Command {\n\n    public static DockerComposeBuilder newBuilder() {\n        return new DockerComposeBuilder();\n    }\n\n    public static final class DockerComposeBuilder extends Command.Builder<DockerCompose> {\n        String composeFile;\n\n        boolean up = true;\n        boolean detach = false;\n\n        public DockerComposeBuilder file(String composeFile) {\n            this.composeFile = composeFile;\n            return this;\n        }\n\n        public DockerComposeBuilder duplicate() {\n            return (DockerComposeBuilder) super.duplicate();\n        }\n\n        public DockerComposeBuilder up() {\n            this.up = true;\n            return this;\n        }\n\n        public DockerComposeBuilder detach() {\n            this.detach = true;\n            return this;\n        }\n\n        public DockerComposeBuilder down() {\n            this.up = false;\n            return this;\n        }\n\n        public DockerCompose build() {\n\n            ArrayList<String> list = new ArrayList<>();\n            list.add(\"docker-compose\");\n            if (composeFile != null && !composeFile.isEmpty()) {\n                list.add(\"-f\");\n                list.add(composeFile);\n            }\n            list.add(up ? \"up\" : \"down\");\n            if (detach) {\n                list.add(\"-d\");\n            }\n\n            return new DockerCompose(list);\n        }\n    }\n\n    DockerCompose(List<String> cmd) {\n        super(cmd);\n        super.env.put(\"COMPOSE_PROJECT_NAME\", \"first-network\");\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/test/java/org/hyperleder/fabric/shim/integration/util/FabricState.java",
    "content": "/*\nCopyright IBM Corp. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\npackage org.hyperleder.fabric.shim.integration.util;\n\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.util.HashMap;\nimport java.util.Map;\nimport org.hyperleder.fabric.shim.integration.util.Bash.BashBuilder;\n\npublic final class FabricState {\n\n    private static final FabricState state = new FabricState();\n\n    private boolean started = false;\n\n    public static FabricState getState() {\n        return state;\n    }\n\n    public synchronized void start() {\n\n        if (!this.started) {\n            BashBuilder bashBuilder = new Bash.BashBuilder().cmd(\"src/test/resources/scripts/mfsetup.sh\");\n            bashBuilder.build().run();\n            this.started = true;\n        } else {\n            System.out.println(\"Fabric already started....\");\n        }\n    }\n\n    public Map<String, String> orgEnv(String org) {\n        Path currentRelativePath = Paths.get(\"\");\n        String s = currentRelativePath.toAbsolutePath().toString();\n\n        Map<String, String> env = new HashMap<>();\n\n        env.put(\n                \"CORE_PEER_MSPCONFIGPATH\",\n                Paths.get(s, \"src/test/resources/_cfg/_msp/\" + org, org + \"admin/msp\")\n                        .toString());\n        env.put(\"CORE_PEER_LOCALMSPID\", org + \"MSP\");\n        env.put(\"CORE_PEER_ADDRESS\", org + \"peer-api.127-0-0-1.nip.io:8080\");\n\n        System.out.println(env);\n        return env;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/test/java/org/hyperleder/fabric/shim/integration/util/InvokeHelper.java",
    "content": "package org.hyperleder.fabric.shim.integration.util;\n\nimport java.util.Arrays;\nimport java.util.Map;\nimport java.util.stream.Collectors;\nimport org.hyperleder.fabric.shim.integration.util.Command.Result;\nimport org.hyperleder.fabric.shim.integration.util.Peer.PeerBuilder;\n\npublic class InvokeHelper {\n\n    private String ccname;\n    private String channel;\n\n    public static InvokeHelper newHelper(String ccname, String channel) {\n\n        InvokeHelper ih = new InvokeHelper();\n\n        ih.ccname = ccname;\n        ih.channel = channel;\n\n        return ih;\n    }\n\n    public String invoke(String org, String... args) {\n        Map<String, String> orgEnv = FabricState.getState().orgEnv(org);\n        PeerBuilder coreBuilder = Peer.newBuilder().ccname(ccname).channel(channel);\n\n        Result r = coreBuilder.argsTx(args).build(orgEnv).run();\n        System.out.println(r.stdout);\n        String text = r.stdout.stream()\n                .filter(line -> line.matches(\".*chaincodeInvokeOrQuery.*\"))\n                .collect(Collectors.joining(System.lineSeparator()))\n                .trim();\n\n        if (!text.contains(\"result: status:200\")) {\n            Command logsCommand = new Command(Arrays.asList(\"docker\", \"logs\", \"microfab\"), orgEnv);\n            logsCommand.run();\n            throw new RuntimeException(text);\n        }\n\n        int payloadIndex = text.indexOf(\"payload:\");\n        if (payloadIndex > 1) {\n            return text.substring(payloadIndex + 9, text.length() - 1);\n        }\n        return \"success\";\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/test/java/org/hyperleder/fabric/shim/integration/util/Peer.java",
    "content": "/*\nCopyright IBM Corp. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\npackage org.hyperleder.fabric.shim.integration.util;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport org.json.JSONArray;\nimport org.json.JSONObject;\n\n/** Represents the 'peer' cli command */\npublic final class Peer extends Command {\n\n    public static PeerBuilder newBuilder() {\n        return new PeerBuilder();\n    }\n\n    public static final class PeerBuilder extends Command.Builder<Peer> {\n        String tlsArgs;\n        String orderer;\n        String channel;\n        String ccname;\n        boolean evaluate = false;\n        int waitForEventTimeout;\n        List<String> args = new ArrayList<String>();\n        Map<String, String> transientData;\n\n        public PeerBuilder duplicate() {\n            try {\n                return (PeerBuilder) this.clone();\n            } catch (CloneNotSupportedException e) {\n\n                e.printStackTrace();\n                return null;\n            }\n        }\n\n        public PeerBuilder tlsArgs(String tlsArgs) {\n            this.tlsArgs = tlsArgs;\n            return this;\n        }\n\n        public PeerBuilder orderer(String orderer) {\n            this.orderer = orderer;\n            return this;\n        }\n\n        public PeerBuilder channel(String channel) {\n            this.channel = channel;\n            return this;\n        }\n\n        public PeerBuilder ccname(String ccname) {\n            this.ccname = ccname;\n            return this;\n        }\n\n        public PeerBuilder evaluate() {\n            this.evaluate = true;\n            return this;\n        }\n\n        public PeerBuilder invoke() {\n            this.evaluate = false;\n            return this;\n        }\n\n        public PeerBuilder argsTx(List<String> args) {\n            this.args = args;\n            return this;\n        }\n\n        public PeerBuilder argsTx(String[] argsArray) {\n            this.args = Arrays.asList(argsArray);\n            return this;\n        }\n\n        public PeerBuilder transientData(Map<String, String> transientData) {\n            this.transientData = transientData;\n            return this;\n        }\n\n        public PeerBuilder waitForEvent(int seconds) {\n            this.waitForEventTimeout = seconds;\n            return this;\n        }\n\n        public PeerBuilder waitForEvent() {\n            this.waitForEvent(0);\n            return this;\n        }\n\n        private String transientToString() {\n            JSONObject json = new JSONObject(this.transientData);\n            return \"'\" + json.toString() + \"'\";\n        }\n\n        private String argsToString() {\n            JSONArray array = new JSONArray(this.args);\n            JSONObject json = new JSONObject();\n            json.put(\"Args\", array);\n            return json.toString();\n        }\n\n        public Peer build(Map<String, String> additionalEnv) {\n\n            ArrayList<String> list = new ArrayList<>();\n            list.add(\"peer\");\n            list.add(\"chaincode\");\n            list.add(evaluate ? \"query\" : \"invoke\");\n            if (tlsArgs != null && !tlsArgs.isEmpty()) {\n                list.add(tlsArgs);\n            }\n\n            if (channel == null || channel.isEmpty()) {\n                throw new RuntimeException(\"Channel should be set\");\n            }\n            list.add(\"-C\");\n            list.add(channel);\n\n            if (ccname == null || ccname.isEmpty()) {\n                throw new RuntimeException(\"Chaincode name should be set\");\n            }\n            list.add(\"-n\");\n            list.add(ccname);\n\n            if (args == null || args.isEmpty()) {\n                throw new RuntimeException(\"Args should be set\");\n            }\n            list.add(\"-c\");\n            list.add(argsToString());\n\n            if (transientData != null && !transientData.isEmpty()) {\n                list.add(\"--transient\");\n                list.add(transientToString());\n            }\n\n            if (waitForEventTimeout > 0) {\n                list.add(\"--waitForEvent --waitForEventTimeout\");\n                list.add(waitForEventTimeout + \"s\");\n            } else if (waitForEventTimeout == 0) {\n                list.add(\"--waitForEvent\");\n            }\n\n            list.add(\"--orderer\");\n            list.add(\"orderer-api.127-0-0-1.nip.io:8080\");\n            list.add(\"--peerAddresses\");\n            list.add(\"org1peer-api.127-0-0-1.nip.io:8080\");\n            list.add(\"--peerAddresses\");\n            list.add(\"org2peer-api.127-0-0-1.nip.io:8080\");\n\n            return new Peer(list, additionalEnv);\n        }\n    }\n\n    Peer(List<String> cmd, Map<String, String> additionalEnv) {\n        super(cmd, additionalEnv);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/test/resources/docker-compose-microfab.yaml",
    "content": "# Copyright IBM Corp. All Rights Reserved.\n#\n# SPDX-License-Identifier: Apache-2.0\n#\n\nversion: '2'\n\nservices:\n\n  microfab:\n    container_name: microfab\n    image: ghcr.io/hyperledger-labs/microfab\n    tty: true\n    environment:\n      - MICROFAB_CONFIG={\"couchdb\":false,\"endorsing_organizations\":[{\"name\":\"org1\"},{\"name\":\"org2\"}],\"channels\":[{\"name\":\"sachannel\",\"endorsing_organizations\":[\"org1\",\"org2\"]}],\"capability_level\":\"V2_5\"}\n      - FABRIC_LOGGING_SPEC=info\n    ports:\n      - 8080:8080\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/test/resources/scripts/ccutils.sh",
    "content": "#!/bin/bash\n\nC_RESET='\\033[0m'\nC_RED='\\033[0;31m'\nC_GREEN='\\033[0;32m'\nC_BLUE='\\033[0;34m'\nC_YELLOW='\\033[1;33m'\n\nexport VERBOSE=true\nexport MAX_RETRY=3\nexport DELAY=5\n\n\n\nfunction setGlobals() {\n  local USING_ORG=$1\n  infoln \"Using organization ${USING_ORG}\"\n  if [ $USING_ORG -eq 1 ]; then\n    export CORE_PEER_LOCALMSPID=\"org1MSP\"\n    export CORE_PEER_MSPCONFIGPATH=${CFG}/_msp/org1/org1admin/msp\n    export CORE_PEER_ADDRESS=org1peer-api.127-0-0-1.nip.io:8080\n  elif [ $USING_ORG -eq 2 ]; then\n    export CORE_PEER_LOCALMSPID=\"org2MSP\"\n    export CORE_PEER_MSPCONFIGPATH=${CFG}/_msp/org2/org2admin/msp\n    export CORE_PEER_ADDRESS=org2peer-api.127-0-0-1.nip.io:8080\n  else\n    errorln \"ORG Unknown\"\n  fi\n\n  if [ \"$VERBOSE\" == \"true\" ]; then\n    env | grep CORE\n  fi\n}\n\n# installChaincode PEER ORG\nfunction installChaincode() {\n  ORG=$1\n  setGlobals $ORG\n  set -x\n  peer lifecycle chaincode queryinstalled --output json | jq -r 'try (.installed_chaincodes[].package_id)' | grep ^${PACKAGE_ID}$ >&log.txt\n  if test $? -ne 0; then\n    peer lifecycle chaincode install ${CC_NAME}.tar.gz >&log.txt\n    res=$?\n  fi\n  { set +x; } 2>/dev/null\n  cat log.txt\n  verifyResult $res \"Chaincode installation on peer0.org${ORG} has failed\"\n  successln \"Chaincode is installed on peer0.org${ORG}\"\n}\n\n# queryInstalled PEER ORG\nfunction queryInstalled() {\n  ORG=$1\n  setGlobals $ORG\n  set -x\n  peer lifecycle chaincode queryinstalled --output json | jq -r 'try (.installed_chaincodes[].package_id)' | grep ^${PACKAGE_ID}$ >&log.txt\n  res=$?\n  { set +x; } 2>/dev/null\n  cat log.txt\n  verifyResult $res \"Query installed on peer0.org${ORG} has failed\"\n  successln \"Query installed successful on peer0.org${ORG} on channel\"\n}\n\n# approveForMyOrg VERSION PEER ORG\nfunction approveForMyOrg() {\n  ORG=$1\n  setGlobals $ORG\n  set -x\n  peer lifecycle chaincode approveformyorg -o orderer-api.127-0-0-1.nip.io:8080 --channelID $CHANNEL_NAME --name ${CC_NAME} ${COLLECTIONS_CFG} --version ${CC_VERSION} --package-id ${PACKAGE_ID} --sequence ${CC_SEQUENCE} >&log.txt\n  res=$?\n  { set +x; } 2>/dev/null\n  cat log.txt\n  verifyResult $res \"Chaincode definition approved on peer0.org${ORG} on channel '$CHANNEL_NAME' failed\"\n  successln \"Chaincode definition approved on peer0.org${ORG} on channel '$CHANNEL_NAME'\"\n}\n\n# checkCommitReadiness VERSION PEER ORG\nfunction checkCommitReadiness() {\n  ORG=$1\n  shift 1\n  setGlobals $ORG\n  infoln \"Checking the commit readiness of the chaincode definition on peer0.org${ORG} on channel '$CHANNEL_NAME'...\"\n  local rc=1\n  local COUNTER=1\n  # continue to poll\n  # we either get a successful response, or reach MAX RETRY\n  while [ $rc -ne 0 -a $COUNTER -lt $MAX_RETRY ]; do\n    sleep $DELAY\n    infoln \"Attempting to check the commit readiness of the chaincode definition on peer0.org${ORG}, Retry after $DELAY seconds.\"\n    set -x\n    peer lifecycle chaincode checkcommitreadiness --channelID $CHANNEL_NAME --name ${CC_NAME} --version ${CC_VERSION} ${COLLECTIONS_CFG}  --sequence ${CC_SEQUENCE}  --output json >&log.txt\n    res=$?\n    { set +x; } 2>/dev/null\n    let rc=0\n    for var in \"$@\"; do\n      grep \"$var\" log.txt &>/dev/null || let rc=1\n    done\n    COUNTER=$(expr $COUNTER + 1)\n  done\n  cat log.txt\n  if test $rc -eq 0; then\n    infoln \"Checking the commit readiness of the chaincode definition successful on peer0.org${ORG} on channel '$CHANNEL_NAME'\"\n  else\n    fatalln \"After $MAX_RETRY attempts, Check commit readiness result on peer0.org${ORG} is INVALID!\"\n  fi\n}\n\n# commitChaincodeDefinition VERSION PEER ORG (PEER ORG)...\nfunction commitChaincodeDefinition() {\n  parsePeerConnectionParameters $@\n  res=$?\n  verifyResult $res \"Invoke transaction failed on channel '$CHANNEL_NAME' due to uneven number of peer and org parameters \"\n\n  # while 'peer chaincode' command can get the orderer endpoint from the\n  # peer (if join was successful), let's supply it directly as we know\n  # it using the \"-o\" option\n  set -x\n  peer lifecycle chaincode commit -o orderer-api.127-0-0-1.nip.io:8080  --channelID $CHANNEL_NAME --name ${CC_NAME} \"${PEER_CONN_PARMS[@]}\" --version ${CC_VERSION} ${COLLECTIONS_CFG}  --sequence ${CC_SEQUENCE} >&log.txt\n  res=$?\n  { set +x; } 2>/dev/null\n  cat log.txt\n  verifyResult $res \"Chaincode definition commit failed on peer0.org${ORG} on channel '$CHANNEL_NAME' failed\"\n  successln \"Chaincode definition committed on channel '$CHANNEL_NAME'\"\n}\n\n# queryCommitted ORG\nfunction queryCommitted() {\n  ORG=$1\n  setGlobals $ORG\n  EXPECTED_RESULT=\"Version: ${CC_VERSION}, Sequence: ${CC_SEQUENCE}, Endorsement Plugin: escc, Validation Plugin: vscc\"\n  infoln \"Querying chaincode definition on peer0.org${ORG} on channel '$CHANNEL_NAME'...\"\n  local rc=1\n  local COUNTER=1\n  # continue to poll\n  # we either get a successful response, or reach MAX RETRY\n  while [ $rc -ne 0 -a $COUNTER -lt $MAX_RETRY ]; do\n    sleep $DELAY\n    infoln \"Attempting to Query committed status on peer0.org${ORG}, Retry after $DELAY seconds.\"\n    set -x\n    peer lifecycle chaincode querycommitted --channelID $CHANNEL_NAME --name ${CC_NAME} >&log.txt\n    res=$?\n    { set +x; } 2>/dev/null\n    test $res -eq 0 && VALUE=$(cat log.txt | grep -o '^Version: '$CC_VERSION', Sequence: [0-9]*, Endorsement Plugin: escc, Validation Plugin: vscc')\n    test \"$VALUE\" = \"$EXPECTED_RESULT\" && let rc=0\n    COUNTER=$(expr $COUNTER + 1)\n  done\n  cat log.txt\n  if test $rc -eq 0; then\n    successln \"Query chaincode definition successful on peer0.org${ORG} on channel '$CHANNEL_NAME'\"\n  else\n    fatalln \"After $MAX_RETRY attempts, Query chaincode definition result on peer0.org${ORG} is INVALID!\"\n  fi\n}\n\nfunction chaincodeInvokeInit() {\n  parsePeerConnectionParameters $@\n  res=$?\n  verifyResult $res \"Invoke transaction failed on channel '$CHANNEL_NAME' due to uneven number of peer and org parameters \"\n\n  # while 'peer chaincode' command can get the orderer endpoint from the\n  # peer (if join was successful), let's supply it directly as we know\n  # it using the \"-o\" option\n  set -x\n  fcn_call='{\"function\":\"'${CC_INIT_FCN}'\",\"Args\":[]}'\n  infoln \"invoke fcn call:${fcn_call}\"\n  peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile \"$ORDERER_CA\" -C $CHANNEL_NAME -n ${CC_NAME} \"${PEER_CONN_PARMS[@]}\" --isInit -c ${fcn_call} >&log.txt\n  res=$?\n  { set +x; } 2>/dev/null\n  cat log.txt\n  verifyResult $res \"Invoke execution on $PEERS failed \"\n  successln \"Invoke transaction successful on $PEERS on channel '$CHANNEL_NAME'\"\n}\n\nfunction chaincodeQuery() {\n  ORG=$1\n  setGlobals $ORG\n  infoln \"Querying on peer0.org${ORG} on channel '$CHANNEL_NAME'...\"\n  local rc=1\n  local COUNTER=1\n  # continue to poll\n  # we either get a successful response, or reach MAX RETRY\n  while [ $rc -ne 0 -a $COUNTER -lt $MAX_RETRY ]; do\n    sleep $DELAY\n    infoln \"Attempting to Query peer0.org${ORG}, Retry after $DELAY seconds.\"\n    set -x\n    peer chaincode query -C $CHANNEL_NAME -n ${CC_NAME} -c '{\"Args\":[\"org.hyperledger.fabric:GetMetadata\"]}' >&log.txt\n    res=$?\n    { set +x; } 2>/dev/null\n    let rc=$res\n    COUNTER=$(expr $COUNTER + 1)\n  done\n  cat log.txt\n  if test $rc -eq 0; then\n    successln \"Query successful on peer0.org${ORG} on channel '$CHANNEL_NAME'\"\n  else\n    fatalln \"After $MAX_RETRY attempts, Query result on peer0.org${ORG} is INVALID!\"\n  fi\n}\n\n\nfunction packageChaincode() {\n  set -x\n  peer lifecycle chaincode package ${CC_NAME}.tar.gz --path ${CC_SRC_PATH} --lang ${CC_RUNTIME_LANGUAGE} --label ${CC_NAME} >&log.txt\n  res=$?\n  PACKAGE_ID=$(peer lifecycle chaincode calculatepackageid ${CC_NAME}.tar.gz)\n  { set +x; } 2>/dev/null\n  cat log.txt\n  verifyResult $res \"Chaincode packaging has failed\"\n  successln \"Chaincode is packaged\"\n}\n\n# println echos string\nfunction println() {\n  echo -e \"$1\"\n}\n\n# errorln echos i red color\nfunction errorln() {\n  println \"${C_RED}${1}${C_RESET}\"\n}\n\n# successln echos in green color\nfunction successln() {\n  println \"${C_GREEN}${1}${C_RESET}\"\n}\n\n# infoln echos in blue color\nfunction infoln() {\n  println \"${C_BLUE}${1}${C_RESET}\"\n}\n\n# warnln echos in yellow color\nfunction warnln() {\n  println \"${C_YELLOW}${1}${C_RESET}\"\n}\n\n# fatalln echos in red color and exits with fail status\nfunction fatalln() {\n  errorln \"$1\"\n  exit 1\n}\n\nfunction verifyResult() {\n  if [ $1 -ne 0 ]; then\n    fatalln \"$2\"\n  fi\n}\n\n# parsePeerConnectionParameters $@\n# Helper function that sets the peer connection parameters for a chaincode\n# operation\nfunction parsePeerConnectionParameters() {\n  PEER_CONN_PARMS=()\n  PEERS=\"\"\n  while [ \"$#\" -gt 0 ]; do\n    setGlobals $1\n    PEER=\"peer0.org$1\"\n    ## Set peer addresses\n    if [ -z \"$PEERS\" ]\n    then\n\tPEERS=\"$PEER\"\n    else\n\tPEERS=\"$PEERS $PEER\"\n    fi\n    PEER_CONN_PARMS=(\"${PEER_CONN_PARMS[@]}\" --peerAddresses $CORE_PEER_ADDRESS)\n    ## Set path to TLS certificate\n    CA=PEER0_ORG$1_CA\n    TLSINFO=(--tlsRootCertFiles \"${!CA}\")\n    PEER_CONN_PARMS=(\"${PEER_CONN_PARMS[@]}\" \"${TLSINFO[@]}\")\n    # shift by one to get to the next organization\n    shift\n  done\n}"
  },
  {
    "path": "fabric-chaincode-integration-test/src/test/resources/scripts/collection_config.json",
    "content": "[\n{\n  \"name\": \"col\",\n  \"policy\": \"OR( OR('org1MSP.member','org1MSP.admin') , OR('org2MSP.member','org2MSP.admin') )\",\n  \"blockToLive\": 100000,\n  \"maxPeerCount\": 1,\n  \"requiredPeerCount\": 1\n}\n]\n"
  },
  {
    "path": "fabric-chaincode-integration-test/src/test/resources/scripts/mfsetup.sh",
    "content": "#!/bin/bash\nset -x\n\nDIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\" )\"/.. && pwd )\"\nexport CFG=\"${DIR}/_cfg\"\nmkdir -p \"${CFG}\"\n\n\n# ---\n# Setup up Microfab image\n# using the IBM tagged version until labs workflow is updated\ndocker rm -f microfab || true\n\nexport MICROFAB_CONFIG='{\"couchdb\":false,\"endorsing_organizations\":[{\"name\":\"org1\"},{\"name\":\"org2\"}],\"channels\":[{\"name\":\"sachannel\",\"endorsing_organizations\":[\"org1\",\"org2\"]}],\"capability_level\":\"V2_5\"}'\n\ndocker run  --name microfab \\\n            -d \\\n            -p 8080:8080 \\\n            --add-host host.docker.internal:host-gateway \\\n            --rm \\\n            -e MICROFAB_CONFIG=\"${MICROFAB_CONFIG}\" \\\n            -e FABRIC_LOGGING_SPEC=info \\\n            ghcr.io/hyperledger-labs/microfab\ntimeout 60s bash -c 'docker logs -f microfab | grep --max-count=1 \"Microfab started\"'\n\ncurl -sSL http://console.localho.st:8080/ak/api/v1/components > $CFG/cfg.json\nnpx @hyperledger-labs/weft microfab -w $CFG/_wallets -p $CFG/_gateways -m $CFG/_msp -f --config $CFG/cfg.json\n\n# bring in the helper bash scripts\n. $DIR/scripts/ccutils.sh\n\n\nfunction deployCC() {\n    ## package the chaincode\n    packageChaincode\n\n    ## Install chaincode on peer0.org1 and peer0.org2\n    infoln \"Installing chaincode on peer0.org1...\"\n    installChaincode 1\n    infoln \"Install chaincode on peer0.org2...\"\n    installChaincode 2\n\n    ## query whether the chaincode is installed\n    queryInstalled 1\n\n    ## approve the definition for org1\n    approveForMyOrg 1\n\n    ## check whether the chaincode definition is ready to be committed\n    ## expect org1 to have approved and org2 not to\n    checkCommitReadiness 1 \"\\\"org1MSP\\\": true\" \"\\\"org2MSP\\\": false\"\n    checkCommitReadiness 2 \"\\\"org1MSP\\\": true\" \"\\\"org2MSP\\\": false\"\n\n    ## now approve also for org2\n    approveForMyOrg 2\n\n    ## check whether the chaincode definition is ready to be committed\n    ## expect them both to have approved\n    checkCommitReadiness 1 \"\\\"org1MSP\\\": true\" \"\\\"org2MSP\\\": true\"\n    checkCommitReadiness 2 \"\\\"org1MSP\\\": true\" \"\\\"org2MSP\\\": true\"\n\n    ## now that we know for sure both orgs have approved, commit the definition\n    commitChaincodeDefinition 1 2\n\n    ## query on both orgs to see that the definition committed successfully\n    queryCommitted 1\n    queryCommitted 2\n}\n#./gradlew -I ./chaincode-init.gradle  -PchaincodeRepoDir=$(realpath ./fabric-chaincode-integration-test/src/contracts/fabric-ledger-api/repository) publishShimPublicationToFabricRepository\n\nexport CC_SRC_PATH=\"${DIR}/../../contracts/fabric-ledger-api\"\nexport CC_NAME=\"ledgercc\"\nexport CC_RUNTIME_LANGUAGE=java\nexport CC_VERSION=1\nexport CC_SEQUENCE=1\nexport CHANNEL_NAME=sachannel\nexport COLLECTIONS_CFG=\"\"\ndeployCC\n\nexport CC_SRC_PATH=\"${DIR}/../../contracts/bare-gradle\"\nexport CC_NAME=\"baregradlecc\"\ndeployCC\n\nexport CC_SRC_PATH=\"${DIR}/../../contracts/bare-maven\"\nexport CC_NAME=\"baremaven\"\ndeployCC\n\nexport CC_SRC_PATH=\"${DIR}/../../contracts/wrapper-maven\"\nexport CC_NAME=\"wrappermaven\"\ndeployCC\n\nexport COLLECTIONS_CFG=\"--collections-config ${CFG}/../scripts/collection_config.json\"\nexport CC_SRC_PATH=\"${DIR}/../../contracts/fabric-shim-api\"\nexport CC_NAME=\"shimcc\"\ndeployCC\n"
  },
  {
    "path": "fabric-chaincode-shim/build.gradle",
    "content": "/*\n * Copyright IBM Corp. 2018 All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\nplugins {\n    id 'maven-publish'\n    id 'signing'\n    id 'jacoco'\n    id 'pmd'\n    id \"com.gradleup.nmcp\"\n}\n\npmd {\n    toolVersion = '7.20.0'\n    ruleSetFiles = files('../pmd-ruleset.xml')\n    ruleSets = [] // explicitly set to empty to avoid using the default configuration\n    ignoreFailures = false\n}\n\npmdTest.enabled = false\n\ndependencyLocking {\n    lockAllConfigurations()\n}\n\ntasks.withType(Test).configureEach {\n    systemProperty 'CORE_CHAINCODE_LOGGING_LEVEL', 'DEBUG'\n}\n\ndependencies {\n    constraints {\n        pmd('org.apache.commons:commons-lang3:3.19.0') {\n            because('CVE-2025-48924')\n        }\n    }\n    implementation platform('com.google.protobuf:protobuf-bom:4.34.1')\n    implementation platform('io.grpc:grpc-bom:1.80.0')\n    implementation platform('io.opentelemetry:opentelemetry-bom:1.61.0')\n    implementation platform(\"org.bouncycastle:bc-jdk18on-bom:1.84\")\n\n    implementation 'org.hyperledger.fabric:fabric-protos:0.3.7'\n    implementation 'org.bouncycastle:bcpkix-jdk18on'\n    implementation 'org.bouncycastle:bcprov-jdk18on'\n    implementation 'io.github.classgraph:classgraph:4.8.184'\n    implementation 'com.github.erosb:everit-json-schema:1.14.6'\n    implementation 'org.json:json:20251224'\n    implementation 'com.google.protobuf:protobuf-java-util'\n\n    implementation 'io.grpc:grpc-netty-shaded'\n    implementation 'io.grpc:grpc-protobuf'\n    implementation 'io.grpc:grpc-stub'\n    testImplementation 'io.grpc:grpc-inprocess'\n\n    implementation 'io.opentelemetry:opentelemetry-api'\n    implementation 'io.opentelemetry.proto:opentelemetry-proto:1.10.0-alpha'\n    implementation 'io.opentelemetry:opentelemetry-sdk'\n    implementation 'io.opentelemetry:opentelemetry-sdk-extension-autoconfigure'\n    implementation 'io.opentelemetry:opentelemetry-sdk-trace'\n    implementation 'io.opentelemetry:opentelemetry-exporter-otlp'\n    implementation 'io.opentelemetry:opentelemetry-extension-trace-propagators'\n    implementation 'io.opentelemetry.semconv:opentelemetry-semconv:1.40.0'\n    implementation 'io.opentelemetry.instrumentation:opentelemetry-grpc-1.6:2.26.1-alpha'\n}\n\nsourceSets {\n    main {\n        java {\n            srcDirs 'src/main/java'\n        }\n    }\n\n    test {\n        java {\n            srcDir 'src/test/java'\n        }\n    }\n\n}\n\njacocoTestReport {\n    afterEvaluate {\n        classDirectories.from = files(classDirectories.files.collect {\n            fileTree(dir: it, exclude: 'org/hyperledger/fabric/protos/**')\n        })\n    }\n}\n\njacocoTestCoverageVerification {\n    violationRules {\n        rule {\n            element = 'CLASS'\n            excludes = ['org.hyperledger.fabric.shim.helper.Channel',\n                        'org.hyperledger.fabric.shim.impl.Handler',\n                        'org.hyperledger.fabric.shim.impl.ChaincodeSupportStream.1',\n                        'org.hyperledger.fabric.contract.ContractRouter',\n                        'org.hyperledger.fabric.contract.routing.impl.ContractDefinitionImpl',\n                        'org.hyperledger.fabric.contract.routing.RoutingRegistry',\n                        'org.hyperledger.fabric.contract.execution.impl.ContractInvocationRequest',\n                        'org.hyperledger.fabric.contract.routing.TransactionType',\n                        'org.hyperledger.fabric.contract.metadata.MetadataBuilder',\n                        'org.hyperledger.fabric.shim.ChaincodeBase*',\n                        'org.hyperledger.fabric.shim.impl.InvocationTaskManager',\n                        'org.hyperledger.fabric.shim.impl.InvocationStubImpl*',\n                        'org.hyperledger.fabric.shim.impl.ChaincodeSupportClient*',\n                        'org.hyperledger.fabric.shim.impl.InvocationTaskExecutor',\n                        'org.hyperledger.fabric.shim.impl.ChaincodeInvocationTask',\n                        'org.hyperledger.fabric.shim.impl.QueryResultsIteratorImpl*',\n                        'org.hyperledger.fabric.shim.impl.ChaincodeMessageFactory',\n                        'org.hyperledger.fabric.shim.ChaincodeServerProperties']\n            limit {\n                minimum = 0.86\n            }\n        }\n\n        rule {\n            element = 'CLASS'\n            includes = ['org.hyperledger.fabric.shim.helper.Channel',\n                        'org.hyperledger.fabric.contract.ContractRouter',\n                        'org.hyperledger.fabric.contract.execution.impl.ContractInvocationRequest',\n                        'org.hyperledger.fabric.contract.routing.impl.ContractDefinitionImpl',\n                        'org.hyperledger.fabric.contract.routing.RoutingRegistry',\n                        'org.hyperledger.fabric.shim.impl.Handler',\n                        'org.hyperledger.fabric.shim.ChaincodeBase',\n                        'org.hyperledger.fabric.contract.metadata.MetadataBuilder',\n                        'org.hyperledger.fabric.shim.impl.InvocationTaskManager',\n                        'org.hyperledger.fabric.shim.impl.InvocationTaskExecutor',\n                        'org.hyperledger.fabric.shim.impl.ChaincodeSupportClient',\n                        'org.hyperledger.fabric.shim.impl.ChaincodeMessageFactory']\n            limit {\n                minimum = 0.71\n            }\n        }\n    }\n}\n\ntest.finalizedBy(jacocoTestReport)\ntest.finalizedBy(jacocoTestCoverageVerification)\n\ntasks.register('licenseCheck') {\n    group = \"license\"\n    description = \"Checks the License part of each source file\"\n\n    println \"Checking Licences...\"\n    def noSPDX = new LinkedList<File>()\n    def missing = new LinkedList<File>()\n    sourceSets.forEach {\n        sourceSet ->\n            sourceSet.allSource.findAll {\n                !it.path.contains(\"build\") &&\n                  !(it.path.contains(\"test\") && it.path.contains(\"resources\"))\n            }.each {\n                file ->\n                    if (!file.name.contains(\"json\")) {\n                        BufferedReader r = new BufferedReader(new FileReader(file))\n                        def line, hasSPDX = false, hasTraditional = false\n                        while ((line = r.readLine()) != null) {\n                            if (line.contains(\"SPDX-License-Identifier\")) {\n                                hasSPDX = true\n                                break\n                            }\n                            if (line.contains(\"http://www.apache.org/licenses/LICENSE-2.0\")) {\n                                hasTraditional = true\n                                break\n                            }\n                        }\n                        if (!hasSPDX) {\n                            if (hasTraditional) {\n                                noSPDX.add(file)\n                            } else {\n                                missing.add(file)\n                            }\n                        }\n                    }\n            }\n    }\n\n    if (noSPDX.isEmpty()) {\n        println \"All remaining files have Apache 2.0 headers.\"\n    } else {\n        println \"We are standardizing with the SPDX style license headers.\"\n        println \"The following files contain the traditional license headers which are still valid:\"\n        noSPDX.each {\n            f -> println \"\\t\" + f.getPath()\n        }\n        println \"If you need to make a content update, please replace the Apache license header comment text with:\"\n        println \"\\tSPDX-License-Identifier: Apache-2.0\\n\"\n    }\n\n    if (!missing.isEmpty()) {\n        def error = \"The following files are missing Apache 2.0 headers:\\n\"\n        missing.each {\n            f -> error += f.getPath() + \"\\n\"\n        }\n        error += \"Fatal Error - All files must have a license header\"\n        throw new IllegalArgumentException(error)\n    }\n}\n\n\njavadoc {\n    failOnError = true\n    excludes = ['org/hyperledger/fabric/contract/ContextFactory.java',\n                'org/hyperledger/fabric/contract/ContractRouter.java',\n                'org/hyperledger/fabric/contract/ContractRuntimeException.java',\n                'org/hyperledger/fabric/contract/execution/**',\n                'org/hyperledger/fabric/contract/metadata/**',\n                'org/hyperledger/fabric/contract/routing/**',\n                'org/hyperledger/fabric/contract/systemcontract/**',\n                'org/hyperledger/fabric/ledger/**',\n                'org/hyperledger/fabric/shim/helper/**',\n                'org/hyperledger/fabric/**/impl/**']\n\n    source = sourceSets.main.allJava\n\n    classpath = sourceSets.main.runtimeClasspath\n\n    options.addStringOption('Xdoclint:none', '-quiet')\n    options.addStringOption('Xwerror', '-quiet')\n    options.overview = \"src/main/java/org/hyperledger/fabric/overview.html\"\n\n}\n\ndef final stagingDeployUrl = layout.buildDirectory.dir('staging-deploy')\n\npublishing {\n    publications {\n        shim(MavenPublication) {\n            groupId = project.group\n            artifactId = project.name\n            version = project.version\n            from components.java\n            pom {\n                name = 'JavaChaincodeShim'\n                packaging = 'jar'\n                description = 'Hyperledger Fabric Java Chaincode Shim'\n                url = 'https://hyperledger.github.io/fabric-chaincode-java/'\n\n                scm {\n                    connection = 'scm:git:https://github.com/hyperledger/fabric-chaincode-java.git'\n                    developerConnection = 'scm:git:ssh://github.com:hyperledger/fabric-chaincode-java.git'\n                    url = 'https://github.com/hyperledger/fabric-chaincode-java'\n                }\n                licenses {\n                    license {\n                        name = 'The Apache License, Version 2.0'\n                        url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'\n                    }\n                }\n\n                developers {\n                    developer {\n                        id = 'denyeart'\n                        name = 'David Enyeart'\n                        email = 'enyeart@us.ibm.com'\n                    }\n                    developer {\n                        id = 'bestbeforetoday'\n                        name = 'Mark S. Lewis'\n                        email = 'Mark.S.Lewis@outlook.com'\n                    }\n                }\n            }\n        }\n    }\n\n    repositories {\n        maven {\n            name = \"GitHub\"\n            url = \"https://maven.pkg.github.com/hyperledger/fabric-chaincode-java\"\n            credentials {\n                username = System.getenv(\"GITHUB_ACTOR\")\n                password = System.getenv(\"GITHUB_TOKEN\")\n            }\n        }\n    }\n}\n\nsigning {\n    def signingKey = findProperty('signingKey')\n    def signingPassword = findProperty('signingPassword')\n    useInMemoryPgpKeys(signingKey, signingPassword)\n\n    required = {\n        gradle.taskGraph.hasTask(\":${project.name}:publishShimPublicationToNmcpRepository\")\n            || gradle.taskGraph.hasTask(\":${project.name}:publishShimPublicationToGitHubRepository\")\n    }\n\n    sign publishing.publications.shim\n}\n\n// Need to specify the sourcesJar task BEFORE the java{withSourcesJar()} so that it picks up the duplicatesStratergy\n// otherwise this fails with a duplicates error.\n// (see https://github.com/gradle/gradle/issues/17236)\n\ntasks.register('sourcesJar', Jar) {\n    duplicatesStrategy = DuplicatesStrategy.INCLUDE\n    archiveClassifier = 'sources'\n    from sourceSets.main.allSource\n}\n\njava {\n    withJavadocJar()\n    withSourcesJar()\n}\n\n\nbuild.dependsOn licenseCheck\n\n// setup more detailed test output formats\nimport org.gradle.api.tasks.testing.logging.TestExceptionFormat\nimport org.gradle.api.tasks.testing.logging.TestLogEvent\n\ntasks.withType(Test).configureEach {\n\n    environment \"CORE_PEER_LOCALMSPID\", \"mymsp\"\n\n    testLogging {\n        // set options for log level LIFECYCLE\n        events TestLogEvent.FAILED,\n          TestLogEvent.PASSED,\n          TestLogEvent.SKIPPED,\n          TestLogEvent.STANDARD_OUT\n        exceptionFormat = TestExceptionFormat.FULL\n        showExceptions = true\n        showCauses = true\n        showStackTraces = true\n\n        // set options for log level DEBUG and INFO\n        debug {\n            events TestLogEvent.STARTED,\n              TestLogEvent.FAILED,\n              TestLogEvent.PASSED,\n              TestLogEvent.SKIPPED,\n              TestLogEvent.STANDARD_ERROR,\n              TestLogEvent.STANDARD_OUT\n            exceptionFormat = TestExceptionFormat.FULL\n        }\n        info.events = debug.events\n        info.exceptionFormat = debug.exceptionFormat\n\n        afterSuite {desc, result ->\n            if (!desc.parent) { // will match the outermost suite\n                def output = \"Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)\"\n                def startItem = '|  ', endItem = '  |'\n                def repeatLength = startItem.length() + output.length() + endItem.length()\n                println('\\n' + ('-' * repeatLength) + '\\n' + startItem + output + endItem + '\\n' +\n                  ('-' * repeatLength))\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/javabuild.sh",
    "content": "#!/bin/bash\n\n#\n#Copyright DTCC 2016 All Rights Reserved.\n#\n#Licensed under the Apache License, Version 2.0 (the \"License\");\n#you may not use this file except in compliance with the License.\n#You may obtain a copy of the License at\n#\n#         http://www.apache.org/licenses/LICENSE-2.0\n#\n#Unless required by applicable law or agreed to in writing, software\n#distributed under the License is distributed on an \"AS IS\" BASIS,\n#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n#See the License for the specific language governing permissions and\n#limitations under the License.\n#\n#\nset -e\nPARENTDIR=$(pwd)\nARCH=`uname -m`\n\npattern='(https?://)?((([^:\\/]+)(:([^\\/]*))?@)?([^:\\/?]+)(:([0-9]+))?)'\n\n[ -n \"$http_proxy\" ] && HTTPPROXY=$http_proxy\n[ -n \"$HTTP_PROXY\" ] && HTTPPROXY=$HTTP_PROXY\n[ -n \"$https_proxy\" ] && HTTPSPROXY=$https_proxy\n[ -n \"$HTTPS_PROXY\" ] && HTTPSPROXY=$HTTPS_PROXY\n\nif [ -n \"$HTTPPROXY\" ]; then\n\tif [[ \"$HTTPPROXY\" =~ $pattern ]]; then\n\t\t[ -n \"${BASH_REMATCH[4]}\" ] && JAVA_OPTS=\"$JAVA_OPTS -Dhttp.proxyUser=${BASH_REMATCH[4]}\"\n\t\t[ -n \"${BASH_REMATCH[6]}\" ] && JAVA_OPTS=\"$JAVA_OPTS -Dhttp.proxyPassword=${BASH_REMATCH[6]}\"\n\t\t[ -n \"${BASH_REMATCH[7]}\" ] && JAVA_OPTS=\"$JAVA_OPTS -Dhttp.proxyHost=${BASH_REMATCH[7]}\"\n\t\t[ -n \"${BASH_REMATCH[9]}\" ] && JAVA_OPTS=\"$JAVA_OPTS -Dhttp.proxyPort=${BASH_REMATCH[9]}\"\n\tfi\nfi\nif [ -n \"$HTTPSPROXY\" ]; then\n\tif [[ \"$HTTPSPROXY\" =~ $pattern ]]; then\n\t\t[ -n \"${BASH_REMATCH[4]}\" ] && JAVA_OPTS=\"$JAVA_OPTS -Dhttps.proxyUser=${BASH_REMATCH[4]}\"\n\t\t[ -n \"${BASH_REMATCH[6]}\" ] && JAVA_OPTS=\"$JAVA_OPTS -Dhttps.proxyPassword=${BASH_REMATCH[6]}\"\n\t\t[ -n \"${BASH_REMATCH[7]}\" ] && JAVA_OPTS=\"$JAVA_OPTS -Dhttps.proxyHost=${BASH_REMATCH[7]}\"\n\t\t[ -n \"${BASH_REMATCH[9]}\" ] && JAVA_OPTS=\"$JAVA_OPTS -Dhttps.proxyPort=${BASH_REMATCH[9]}\"\n\tfi\nfi\n\nexport JAVA_OPTS\n\nif [ x$ARCH == xx86_64 ]\nthen\n    gradle -q -b ${PARENTDIR}/core/chaincode/shim/java/build.gradle clean\n    gradle -q -b ${PARENTDIR}/core/chaincode/shim/java/build.gradle build\n    cp -r ${PARENTDIR}/core/chaincode/shim/java/build/libs /root/\nelse\n    echo \"FIXME: Java Shim code needs work on ppc64le and s390x.\"\n    echo \"Commenting it for now.\"\nfi\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/Logger.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric;\n\nimport java.io.PrintWriter;\nimport java.io.StringWriter;\nimport java.util.function.Supplier;\nimport java.util.logging.Level;\nimport java.util.logging.LogManager;\n\n/** Logger class to use throughout the Contract Implementation. */\npublic class Logger extends java.util.logging.Logger {\n\n    /**\n     * Subclasses must ensure that a parent logger is set appropriately, for example:\n     *\n     * <p>{@code logger.setParent(java.util.logging.Logger.getLogger(\"org.hyperledger.fabric\"))}\n     *\n     * @param name A name for the logger.\n     */\n    protected Logger(final String name) {\n        super(name, null);\n    }\n\n    /**\n     * @param name\n     * @return Logger\n     */\n    public static Logger getLogger(final String name) {\n        Logger result = new Logger(name);\n        result.setParent(java.util.logging.Logger.getLogger(\"org.hyperledger.fabric\"));\n        return result;\n    }\n\n    /** @param msgSupplier */\n    public void debug(final Supplier<String> msgSupplier) {\n        log(Level.FINEST, msgSupplier);\n    }\n\n    /** @param msg */\n    public void debug(final String msg) {\n        log(Level.FINEST, msg);\n    }\n\n    /**\n     * @param class1\n     * @return Logger\n     */\n    public static Logger getLogger(final Class<?> class1) {\n        // important to add the logger to the log manager\n        final Logger result = Logger.getLogger(class1.getName());\n        LogManager.getLogManager().addLogger(result);\n        return result;\n    }\n\n    /** @param message */\n    public void error(final String message) {\n        log(Level.SEVERE, message);\n    }\n\n    /** @param msgSupplier */\n    public void error(final Supplier<String> msgSupplier) {\n        log(Level.SEVERE, msgSupplier);\n    }\n\n    /**\n     * @param throwable\n     * @return Throwable\n     */\n    public String formatError(final Throwable throwable) {\n        if (throwable == null) {\n            return null;\n        }\n\n        final StringWriter buffer = new StringWriter();\n        buffer.append(throwable.getMessage());\n        throwable.printStackTrace(new PrintWriter(buffer));\n\n        final Throwable cause = throwable.getCause();\n        if (cause != null) {\n            buffer.append(\".. caused by ..\");\n            buffer.append(this.formatError(cause));\n        }\n\n        return buffer.toString();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/Logging.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric;\n\nimport java.io.PrintWriter;\nimport java.io.StringWriter;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.logging.Level;\nimport java.util.logging.LogManager;\n\n/**\n * Assistance class to use when logging.\n *\n * <p>For chaincode/contract implementations please use java.util.logging or your own framework. All the Hyperledger\n * Fabric code here is logged in loggers with names starting org.hyperledger\n *\n * <p>Control of this is via the environment variables 'CORE_CHAINCODE_LOGGING_LEVEL' this takes a string that matches\n * the following Java.util.logging levels (case insensitive)\n *\n * <p>CRITICAL, ERROR == Level.SEVERE, WARNING == Level.WARNING, INFO == Level.INFO NOTICE == Level.CONFIG, DEBUG ==\n * Level.FINEST\n */\npublic final class Logging {\n\n    /** Name of the Performance logger. */\n    public static final String PERFLOGGER = \"org.hyperledger.Performance\";\n\n    /** Private Constructor. */\n    private Logging() {}\n\n    /**\n     * Formats a Throwable to a string with details of all the causes.\n     *\n     * @param throwable Exception\n     * @return String formatted with all the details\n     */\n    public static String formatError(final Throwable throwable) {\n        if (throwable == null) {\n            return null;\n        }\n        final StringWriter buffer = new StringWriter();\n        buffer.append(throwable.getMessage()).append(System.lineSeparator());\n\n        throwable.printStackTrace(new PrintWriter(buffer));\n\n        final Throwable cause = throwable.getCause();\n        if (cause != null) {\n            buffer.append(\".. caused by ..\").append(System.lineSeparator());\n            buffer.append(formatError(cause));\n        }\n\n        return buffer.toString();\n    }\n\n    /**\n     * Sets the log level to the the.\n     *\n     * @param newLevel the new logging level\n     */\n    public static void setLogLevel(final String newLevel) {\n\n        final Level l = mapLevel(newLevel);\n        final LogManager logManager = LogManager.getLogManager();\n        // slightly cumbersome approach - but the loggers don't have a 'get children'\n        // so find those that have the correct stem.\n        final List<String> allLoggers = Collections.list(logManager.getLoggerNames());\n        allLoggers.add(\"org.hyperledger\");\n        allLoggers.stream()\n                .filter(name -> name.startsWith(\"org.hyperledger\"))\n                .map(logManager::getLogger)\n                .forEach(logger -> {\n                    if (logger != null) {\n                        logger.setLevel(l);\n                    }\n                });\n    }\n\n    private static Level mapLevel(final String level) {\n        if (level != null) {\n            switch (level.toUpperCase(Locale.getDefault()).trim()) {\n                case \"ERROR\":\n                case \"CRITICAL\":\n                    return Level.SEVERE;\n                case \"WARNING\":\n                case \"WARN\":\n                    return Level.WARNING;\n                case \"INFO\":\n                    return Level.INFO;\n                case \"NOTICE\":\n                    return Level.CONFIG;\n                case \"DEBUG\":\n                    return Level.FINEST;\n                default:\n                    return Level.INFO;\n            }\n        }\n        return Level.INFO;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ClientIdentity.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract;\n\nimport static java.nio.charset.StandardCharsets.UTF_8;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.IOException;\nimport java.security.cert.CertificateException;\nimport java.security.cert.CertificateFactory;\nimport java.security.cert.X509Certificate;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.Map;\nimport org.bouncycastle.asn1.ASN1InputStream;\nimport org.bouncycastle.asn1.ASN1Primitive;\nimport org.bouncycastle.asn1.DEROctetString;\nimport org.hyperledger.fabric.Logger;\nimport org.hyperledger.fabric.protos.msp.SerializedIdentity;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\n/**\n * ClientIdentity represents information about the identity that submitted a transaction. Chaincodes can use this class\n * to obtain information about the submitting identity including a unique ID, the MSP (Membership Service Provider) ID,\n * and attributes. Such information is useful in enforcing access control by the chaincode.\n */\npublic final class ClientIdentity {\n    private static final Logger LOGGER = Logger.getLogger(ContractRouter.class.getName());\n\n    private final String mspId;\n    private final X509Certificate cert;\n    private final Map<String, String> attrs;\n    private final String id;\n    // special OID used by Fabric to save attributes in x.509 certificates\n    private static final String FABRIC_CERT_ATTR_OID = \"1.2.3.4.5.6.7.8.1\";\n\n    /**\n     * Creates new ClientIdentity helper.\n     *\n     * @param stub\n     * @throws CertificateException\n     * @throws JSONException\n     * @throws IOException\n     */\n    public ClientIdentity(final ChaincodeStub stub) throws CertificateException, IOException {\n        final byte[] signingId = stub.getCreator();\n\n        // Create a Serialized Identity protobuf\n        final SerializedIdentity si = SerializedIdentity.parseFrom(signingId);\n        this.mspId = si.getMspid();\n\n        final byte[] idBytes = si.getIdBytes().toByteArray();\n\n        final X509Certificate cert = (X509Certificate)\n                CertificateFactory.getInstance(\"X509\").generateCertificate(new ByteArrayInputStream(idBytes));\n        this.cert = cert;\n\n        // Get the extension where the identity attributes are stored\n        final byte[] extensionValue = cert.getExtensionValue(FABRIC_CERT_ATTR_OID);\n        if (extensionValue != null) {\n            this.attrs = parseAttributes(extensionValue);\n        } else {\n            this.attrs = new HashMap<>();\n        }\n\n        // Populate identity\n        this.id = \"x509::\" + cert.getSubjectDN().getName() + \"::\"\n                + cert.getIssuerDN().getName();\n    }\n\n    /**\n     * getId returns the ID associated with the invoking identity. This ID is guaranteed to be unique within the MSP.\n     *\n     * @return {String} A string in the format: \"x509::{subject DN}::{issuer DN}\"\n     */\n    public String getId() {\n        return this.id;\n    }\n\n    /**\n     * getMSPID returns the MSP ID of the invoking identity.\n     *\n     * @return {String}\n     */\n    public String getMSPID() {\n        return this.mspId;\n    }\n\n    /**\n     * parseAttributes returns a map of the attributes associated with an identity.\n     *\n     * @param extensionValue DER-encoded Octet string stored in the attributes extension of the certificate, as a byte\n     *     array\n     * @return attrMap {Map<String, String>} a map of identity attributes as key value pair strings\n     * @throws IOException\n     */\n    private Map<String, String> parseAttributes(final byte[] extensionValue) throws IOException {\n\n        final Map<String, String> attrMap = new HashMap<>();\n\n        // Create ASN1InputStream from extensionValue\n        try (ByteArrayInputStream inStream = new ByteArrayInputStream(extensionValue);\n                ASN1InputStream asn1InputStream = new ASN1InputStream(inStream)) {\n\n            // Read the DER object\n            final ASN1Primitive derObject = asn1InputStream.readObject();\n            if (derObject instanceof DEROctetString) {\n                final DEROctetString derOctetString = (DEROctetString) derObject;\n\n                // Create attributeString from octets and create JSON object\n                final String attributeString = new String(derOctetString.getOctets(), UTF_8);\n                final JSONObject extJSON = new JSONObject(attributeString);\n                final JSONObject attrs = extJSON.getJSONObject(\"attrs\");\n\n                final Iterator<String> keys = attrs.keys();\n                while (keys.hasNext()) {\n                    final String key = keys.next();\n                    // Populate map with attributes and values\n                    attrMap.put(key, attrs.getString(key));\n                }\n            }\n        } catch (final JSONException error) {\n            // creating a JSON object failed\n            // decoded extensionValue is not a string containing JSON\n            LOGGER.error(() -> LOGGER.formatError(error));\n            // return empty map\n        }\n        return attrMap;\n    }\n\n    /**\n     * getAttributeValue returns the value of the client's attribute named `attrName`. If the invoking identity\n     * possesses the attribute, returns the value of the attribute. If the invoking identity does not possess the\n     * attribute, returns null.\n     *\n     * @param attrName Name of the attribute to retrieve the value from the identity's credentials (such as x.509\n     *     certificate for PKI-based MSPs).\n     * @return {String | null} Value of the attribute or null if the invoking identity does not possess the attribute.\n     */\n    public String getAttributeValue(final String attrName) {\n        return this.attrs.getOrDefault(attrName, null);\n    }\n\n    /**\n     * assertAttributeValue verifies that the invoking identity has the attribute named `attrName` with a value of\n     * `attrValue`.\n     *\n     * @param attrName Name of the attribute to retrieve the value from the identity's credentials (such as x.509\n     *     certificate for PKI-based MSPs)\n     * @param attrValue Expected value of the attribute\n     * @return {boolean} True if the invoking identity possesses the attribute and the attribute value matches the\n     *     expected value. Otherwise, returns false.\n     */\n    public boolean assertAttributeValue(final String attrName, final String attrValue) {\n        return this.attrs.containsKey(attrName) && attrValue.equals(this.attrs.get(attrName));\n    }\n\n    /**\n     * getX509Certificate returns the X509 certificate associated with the invoking identity, or null if it was not\n     * identified by an X509 certificate, for instance if the MSP is implemented with an alternative to PKI such as\n     * [Identity Mixer](https://jira.hyperledger.org/browse/FAB-5673).\n     *\n     * @return {X509Certificate | null}\n     */\n    public X509Certificate getX509Certificate() {\n        return this.cert;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/Context.java",
    "content": "/*\n * Copyright 2019 IBM DTCC All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract;\n\nimport java.io.IOException;\nimport java.security.cert.CertificateException;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.json.JSONException;\n\n/**\n * This context is available to all 'transaction functions' and provides the transaction context. It also provides\n * access to the APIs for the world state using {@link #getStub()}\n *\n * <p>Applications can implement their own versions if they wish to add functionality. All subclasses MUST implement a\n * constructor, for example\n *\n * <pre>{@code\n * public MyContext extends Context {\n *\n *     public MyContext(ChaincodeStub stub) {\n *        super(stub);\n *     }\n * }\n *\n * }</pre>\n */\npublic class Context {\n    /** */\n    protected ChaincodeStub stub;\n\n    /** */\n    protected ClientIdentity clientIdentity;\n\n    /**\n     * Creates new client identity and sets it as a property of the stub.\n     *\n     * @param stub Instance of the {@link ChaincodeStub} to use\n     */\n    public Context(final ChaincodeStub stub) {\n        this.stub = stub;\n        try {\n            this.clientIdentity = new ClientIdentity(stub);\n        } catch (CertificateException | JSONException | IOException e) {\n            throw new ContractRuntimeException(\"Could not create new client identity\", e);\n        }\n    }\n\n    /** @return ChaincodeStub instance to use */\n    public ChaincodeStub getStub() {\n        return this.stub;\n    }\n\n    /** @return ClientIdentity object to use */\n    public ClientIdentity getClientIdentity() {\n        return this.clientIdentity;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContextFactory.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract;\n\nimport org.hyperledger.fabric.shim.ChaincodeStub;\n\n/** Factory to create {@link Context} from {@link ChaincodeStub} by wrapping stub with dynamic proxy. */\npublic final class ContextFactory {\n    private static final ContextFactory INSTANCE = new ContextFactory();\n\n    /** @return ContextFactory */\n    public static ContextFactory getInstance() {\n        return INSTANCE;\n    }\n\n    /**\n     * @param stub\n     * @return Context\n     */\n    public Context createContext(final ChaincodeStub stub) {\n        return new Context(stub);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractInterface.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract;\n\nimport org.hyperledger.fabric.shim.ChaincodeException;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\n\n/**\n * All Contracts should implement this interface, in addition to the\n * {@linkplain org.hyperledger.fabric.contract.annotation.Contract} annotation.\n *\n * <p>All methods on this interface have default implementations; for many contracts it may not be needed to sub-class\n * these.\n *\n * <p>Each method on the Contract that is marked with the {@link org.hyperledger.fabric.contract.annotation.Transaction}\n * annotation is considered a Transaction Function. This is eligible for calling. Each transaction function is supplied\n * with its first parameter being a {@link org.hyperledger.fabric.contract.Context}. The other parameters are supplied\n * at the developer's discretion.\n *\n * <p>The sequence of calls is\n *\n * <pre>\n * createContext()  -&gt; beforeTransaction() -&gt; the transaction function -&gt; afterTransaction()\n * </pre>\n *\n * <p>If any of these functions throws an exception it is considered an error case and the whole transaction is failed.\n * The {@link org.hyperledger.fabric.contract.Context} is a very important object as it provides transactional context\n * for access to current transaction id, ledger state, etc.\n *\n * <p><b>Note on Threading</b>\n *\n * <p>All code should be 'Thread Friendly'. Each method must not rely on instance fields or class side variables for\n * storage. Nor should they use any ThreadLocal Storage. Ledger data is stored via the ledger api available via the\n * {@link Context}.\n *\n * <p>If information needs to be passed from {@link #beforeTransaction(Context)} to {@link #afterTransaction(Context,\n * Object)} or between separate transaction functions when called directly then a subclass of the {@link Context} should\n * be provided.\n */\npublic interface ContractInterface {\n\n    /**\n     * Create context from {@link ChaincodeStub}.\n     *\n     * <p>Default impl provided, but can be overwritten by contract\n     *\n     * @param stub Instance of the ChaincodeStub to use for this transaction\n     * @return instance of the context to use for the current transaction being executed\n     */\n    default Context createContext(final ChaincodeStub stub) {\n        return ContextFactory.getInstance().createContext(stub);\n    }\n\n    /**\n     * Invoked for any transaction that does not exist.\n     *\n     * <p>This will throw an exception. If you wish to alter the exception thrown or if you wish to consider requests\n     * for transactions that don't exist as not an error, subclass this method.\n     *\n     * @param ctx the context as created by {@link #createContext(ChaincodeStub)}.\n     */\n    default void unknownTransaction(final Context ctx) {\n        throw new ChaincodeException(\"Undefined contract method called\");\n    }\n\n    /**\n     * Invoked once before each transaction.\n     *\n     * <p>Any exceptions thrown will fail the transaction, and neither the required transaction or the\n     * {@link #afterTransaction(Context, Object)} will be called\n     *\n     * @param ctx the context as created by {@link #createContext(ChaincodeStub)}.\n     */\n    default void beforeTransaction(final Context ctx) {\n        // Nothing by default\n    }\n\n    /**\n     * Invoked once after each transaction.\n     *\n     * <p>Any exceptions thrown will fail the transaction.\n     *\n     * @param ctx the context as created by {@link #createContext(ChaincodeStub)}.\n     * @param result The object returned from the transaction function if any. As this is a Java object and therefore\n     *     pass-by-reference it is possible to modify this object.\n     */\n    default void afterTransaction(final Context ctx, final Object result) {\n        // Nothing by default\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractRouter.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract;\n\nimport java.io.IOException;\nimport java.util.Properties;\nimport java.util.logging.Logger;\nimport org.hyperledger.fabric.Logging;\nimport org.hyperledger.fabric.contract.execution.ExecutionFactory;\nimport org.hyperledger.fabric.contract.execution.ExecutionService;\nimport org.hyperledger.fabric.contract.execution.InvocationRequest;\nimport org.hyperledger.fabric.contract.metadata.MetadataBuilder;\nimport org.hyperledger.fabric.contract.routing.ContractDefinition;\nimport org.hyperledger.fabric.contract.routing.RoutingRegistry;\nimport org.hyperledger.fabric.contract.routing.TxFunction;\nimport org.hyperledger.fabric.contract.routing.TypeRegistry;\nimport org.hyperledger.fabric.contract.routing.impl.RoutingRegistryImpl;\nimport org.hyperledger.fabric.contract.routing.impl.SerializerRegistryImpl;\nimport org.hyperledger.fabric.metrics.Metrics;\nimport org.hyperledger.fabric.shim.ChaincodeBase;\nimport org.hyperledger.fabric.shim.ChaincodeServer;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.hyperledger.fabric.shim.NettyChaincodeServer;\nimport org.hyperledger.fabric.shim.ResponseUtils;\nimport org.hyperledger.fabric.traces.Traces;\n\n/**\n * Router class routes Init/Invoke requests to contracts. Implements {@link org.hyperledger.fabric.shim.Chaincode}\n * interface.\n *\n * @see ContractInterface\n */\npublic final class ContractRouter extends ChaincodeBase {\n    private static final Logger LOGGER = Logger.getLogger(ContractRouter.class.getName());\n\n    private final RoutingRegistry registry;\n    private final TypeRegistry typeRegistry;\n\n    // Store instances of SerializerInterfaces - identified by the contract\n    // annotation (default is JSON)\n    private final SerializerRegistryImpl serializers;\n    private final ExecutionService executor;\n\n    /**\n     * Take the arguments from the cli, and initiate processing of cli options and environment variables.\n     *\n     * <p>Create the Contract scanner, and the Execution service\n     *\n     * @param args\n     */\n    public ContractRouter(final String[] args) {\n        super();\n        super.initializeLogging();\n        super.processEnvironmentOptions();\n        super.processCommandLineOptions(args);\n        super.validateOptions();\n\n        final Properties props = super.getChaincodeConfig();\n        Metrics.initialize(props);\n        Traces.initialize(props);\n\n        LOGGER.fine(\"ContractRouter<init>\");\n        registry = new RoutingRegistryImpl();\n        typeRegistry = TypeRegistry.getRegistry();\n\n        serializers = new SerializerRegistryImpl();\n\n        try {\n            serializers.findAndSetContents();\n        } catch (InstantiationException | IllegalAccessException e) {\n            final ContractRuntimeException cre = new ContractRuntimeException(\"Unable to locate Serializers\", e);\n            LOGGER.severe(() -> Logging.formatError(cre));\n            throw cre;\n        }\n\n        executor = ExecutionFactory.getInstance().createExecutionService(serializers);\n    }\n\n    /** Locate all the contracts that are available on the classpath. */\n    void findAllContracts() {\n        registry.findAndSetContracts(this.typeRegistry);\n    }\n\n    /**\n     * Start the chaincode container off and running.\n     *\n     * <p>This will send the initial flow back to the peer\n     *\n     * @throws Exception\n     */\n    @SuppressWarnings(\"PMD.AvoidCatchingGenericException\")\n    void startRouting() {\n        try {\n            super.connectToPeer();\n        } catch (final Exception e) {\n            LOGGER.severe(() -> Logging.formatError(e));\n            throw new ContractRuntimeException(\"Unable to start routing\", e);\n        }\n    }\n\n    @SuppressWarnings(\"PMD.AvoidCatchingGenericException\")\n    private Response processRequest(final ChaincodeStub stub) {\n        LOGGER.info(() -> \"Got invoke routing request\");\n        try {\n            if (stub.getStringArgs().isEmpty()) {\n                return ResponseUtils.newSuccessResponse();\n            }\n\n            LOGGER.info(() -> \"Got the invoke request for:\" + stub.getFunction() + \" \" + stub.getParameters());\n            final InvocationRequest request = ExecutionFactory.getInstance().createRequest(stub);\n            final TxFunction txFn = getRouting(request);\n            LOGGER.info(() -> \"Got routing:\" + txFn.getRouting());\n            return executor.executeRequest(txFn, request, stub);\n        } catch (final Throwable throwable) {\n            return ResponseUtils.newErrorResponse(throwable);\n        }\n    }\n\n    @Override\n    public Response invoke(final ChaincodeStub stub) {\n        return processRequest(stub);\n    }\n\n    @Override\n    public Response init(final ChaincodeStub stub) {\n        return processRequest(stub);\n    }\n\n    /**\n     * Given the Invocation Request, return the routing object for this call.\n     *\n     * @param request\n     * @return TxFunction for the request\n     */\n    TxFunction getRouting(final InvocationRequest request) {\n        // request name is the fully qualified 'name:txname'\n        if (registry.containsRoute(request)) {\n            return registry.getTxFn(request);\n        } else {\n            LOGGER.fine(() -> \"Namespace is \" + request);\n            final ContractDefinition contract = registry.getContract(request.getNamespace());\n            return contract.getUnknownRoute();\n        }\n    }\n\n    /**\n     * Main method to start the contract based chaincode.\n     *\n     * @param args\n     */\n    @SuppressWarnings(\"PMD.SignatureDeclareThrowsException\")\n    public static void main(final String[] args) throws Exception {\n\n        final ContractRouter cfc = new ContractRouter(args);\n        cfc.findAllContracts();\n\n        LOGGER.fine(() -> cfc.getRoutingRegistry().toString());\n\n        // Create the Metadata ahead of time rather than have to produce every\n        // time\n        MetadataBuilder.initialize(cfc.getRoutingRegistry(), cfc.getTypeRegistry());\n        LOGGER.info(() -> \"Metadata follows:\" + MetadataBuilder.debugString());\n\n        // check if this should be running in client or server mode\n        if (cfc.isServer()) {\n            LOGGER.info(\"Starting chaincode as server\");\n            ChaincodeServer chaincodeServer = new NettyChaincodeServer(cfc, cfc.getChaincodeServerConfig());\n            chaincodeServer.start();\n        } else {\n            LOGGER.info(\"Starting chaincode as client\");\n            cfc.startRouting();\n        }\n    }\n\n    TypeRegistry getTypeRegistry() {\n        return this.typeRegistry;\n    }\n\n    RoutingRegistry getRoutingRegistry() {\n        return this.registry;\n    }\n\n    /**\n     * Start router and Chaincode server.\n     *\n     * @param chaincodeServer\n     */\n    public void startRouterWithChaincodeServer(final ChaincodeServer chaincodeServer)\n            throws IOException, InterruptedException {\n        findAllContracts();\n        LOGGER.fine(() -> getRoutingRegistry().toString());\n\n        MetadataBuilder.initialize(getRoutingRegistry(), getTypeRegistry());\n        LOGGER.info(() -> \"Metadata follows:\" + MetadataBuilder.debugString());\n\n        chaincodeServer.start();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractRuntimeException.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract;\n\nimport org.hyperledger.fabric.shim.ChaincodeException;\n\n/**\n * Specific RuntimeException for events that occur in the calling and handling of the Contracts, NOT within the contract\n * logic itself.\n *\n * <p><B>FUTURE</b> At some future point we wish to add more diagnostic information into this, for example current tx id\n */\npublic class ContractRuntimeException extends ChaincodeException {\n    /** Generated serial version id. */\n    private static final long serialVersionUID = -884373036398750450L;\n\n    /** @param string */\n    public ContractRuntimeException(final String string) {\n        super(string);\n    }\n\n    /**\n     * @param string\n     * @param cause\n     */\n    public ContractRuntimeException(final String string, final Throwable cause) {\n        super(string, cause);\n    }\n\n    /** @param cause */\n    public ContractRuntimeException(final Throwable cause) {\n        super(cause);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Contact.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.annotation;\n\nimport static java.lang.annotation.RetentionPolicy.RUNTIME;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\n/**\n * Class level annotation that identifies this class as being a contact. Can be populated with email, name and url\n * fields.\n */\n@Retention(RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface Contact {\n\n    /** @return String */\n    String email() default \"\";\n\n    /** @return String */\n    String name() default \"\";\n\n    /** @return String */\n    String url() default \"\";\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Contract.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.annotation;\n\nimport static java.lang.annotation.RetentionPolicy.RUNTIME;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\n/**\n * Class level annotation that identifies this class as being a contract. Can supply information and an alternative name\n * for the contract rather than the classname\n */\n@Retention(RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface Contract {\n\n    /**\n     * The Info object can be supplied to provide additional information about the contract.\n     *\n     * <p>Including title, description, version and license\n     *\n     * @return Info object\n     */\n    Info info() default @Info();\n\n    /**\n     * Contract name.\n     *\n     * <p>Normally the name of the class is used to refer to the contract (name without package). This can be altered if\n     * wished.\n     *\n     * @return Name of the contract to be used instead of the Classname\n     */\n    String name() default \"\";\n\n    /**\n     * Transaction Serializer Classname.\n     *\n     * <p>Fully Qualified Classname of the TRANSACTION serializer that should be used with this contract.\n     *\n     * <p>This is the serializer that is used to parse incoming transaction request parameters and convert the return\n     * type\n     *\n     * @return Default serializer classname\n     */\n    String transactionSerializer() default \"org.hyperledger.fabric.contract.execution.JSONTransactionSerializer\";\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/DataType.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.annotation;\n\nimport static java.lang.annotation.RetentionPolicy.RUNTIME;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\n/**\n * Class level annotation indicating this class represents one of the complex types that can be returned or passed to\n * the transaction functions.\n *\n * <p>These datatypes are used (within the current implementation) for determining the data flow protocol from the\n * Contracts to the SDK and for permitting a fully formed Interface Definition to be created for the contract.\n *\n * <p>Complex types can appear within this definition, and these are identified using this annotation.\n *\n * <p><b>FUTURE</b> To take these annotations are also utilize them for leverage storage\n */\n@Retention(RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface DataType {\n    /**\n     * Namespace of the type.\n     *\n     * @return String\n     */\n    String namespace() default \"\";\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Default.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.annotation;\n\nimport static java.lang.annotation.RetentionPolicy.RUNTIME;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\n/**\n * Default Contract.\n *\n * <p>Class level annotation that defines the contract that is the default contract, and as such invoke of the\n * transaction functions does not need to be qualified by the contract name\n */\n@Retention(RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface Default {}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract.annotation;\n\nimport static java.lang.annotation.RetentionPolicy.RUNTIME;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\n/**\n * Info Details\n *\n * <p>Class level annotation that identifies this class as being an info object. Can supply additional information about\n * the contract, including title, description, version, license and contact information.\n */\n@Retention(RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface Info {\n\n    /** @return String */\n    String title() default \"\";\n\n    /** @return String */\n    String description() default \"\";\n\n    /** @return String */\n    String version() default \"\";\n\n    /** @return String */\n    String termsOfService() default \"\";\n\n    /**\n     * License object that can be populated to include name and url.\n     *\n     * @return License object\n     */\n    License license() default @License();\n\n    /**\n     * Contact object that can be populated with email, name and url fields.\n     *\n     * @return Contact object\n     */\n    Contact contact() default @Contact();\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/License.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.annotation;\n\nimport static java.lang.annotation.RetentionPolicy.RUNTIME;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\n/**\n * Class level annotation that identifies this class as being a license object. Can be populated to include name and\n * url.\n */\n@Retention(RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface License {\n\n    /** @return String */\n    String name() default \"\";\n\n    /** @return String */\n    String url() default \"\";\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Property.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.annotation;\n\nimport static java.lang.annotation.RetentionPolicy.RUNTIME;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\n/**\n * Field and parameter level annotation defining a property of the class.\n *\n * <p>(identified by {@link DataType}) Can also be used on the parameters of transaction functions\n *\n * <p>Example of using this annotation\n *\n * <pre>\n *\n * // max 15 character string, a-z with spaces\n * &#64;Property(schema = {\"pattern\", \"^[a-zA-Z\\\\s]{0,15}$\"})\n * private String text;\n *\n * // How friendly is this on a scale of 1-5, 1 being formal, 5 being familiar\n * &#64;Property(schema = {\"minimum\", \"1\", \"maximum\", \"5\"})\n * private int friendliness = 1;\n *\n * </pre>\n */\n@Retention(RUNTIME)\n@Target({ElementType.FIELD, ElementType.PARAMETER})\npublic @interface Property {\n\n    /**\n     * Allows each property to be defined a detail set of rules to determine the valid types of this data. The format\n     * follows the syntax of the OpenAPI Schema object.\n     *\n     * @return String array of the key-value pairs of the schema\n     */\n    String[] schema() default {};\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Serializer.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.annotation;\n\nimport static java.lang.annotation.RetentionPolicy.RUNTIME;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\n/**\n * Class level annotation that defines the serializer that should be used to convert objects to and from the wire\n * format.\n *\n * <p>This should annotate a class that implements the Serializer interface\n */\n@Retention(RUNTIME)\n@Target({ElementType.TYPE, ElementType.TYPE_USE})\npublic @interface Serializer {\n    /** What is this serializer able to target? */\n    enum TARGET {\n        /** Target transaction functions. */\n        TRANSACTION,\n        /** Target all elements. */\n        ALL\n    }\n\n    /** @return Target of the serializer */\n    TARGET target() default Serializer.TARGET.ALL;\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Transaction.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.annotation;\n\nimport static java.lang.annotation.ElementType.METHOD;\nimport static java.lang.annotation.RetentionPolicy.RUNTIME;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\n/**\n * Method level annotation indicating the method to be a callable transaction function.\n *\n * <p>These functions are called in client SDKs by the combination of\n *\n * <pre>\n *  [contractname]:[transactioname]\n * </pre>\n *\n * Unless specified otherwise, the contract name is the class name (without package) and the transaction name is the\n * method name.\n */\n@Retention(RUNTIME)\n@Target(METHOD)\npublic @interface Transaction {\n\n    /** The intended invocation style for a transaction function. */\n    enum TYPE {\n        /** Transaction is used to submit updates to the ledger. */\n        SUBMIT,\n        /** Transaction is evaluated to query information from the ledger. */\n        EVALUATE\n    }\n\n    /**\n     * Submit semantics.\n     *\n     * <p>TRUE indicates that this function is intended to be called with the 'submit' semantics\n     *\n     * <p>FALSE indicates that this is intended to be called with the evaluate semantics\n     *\n     * @return boolean, default is true\n     * @deprecated Please use intent\n     */\n    @Deprecated\n    boolean submit() default true;\n\n    /**\n     * What are submit semantics for this transaction.\n     *\n     * <dl>\n     *   <dt>SUBMIT\n     *   <dd>indicates that this function is intended to be called with the 'submit' semantics\n     *   <dt>EVALUATE\n     *   <dd>indicates that this is intended to be called with the 'evaluate' semantics\n     * </dl>\n     *\n     * @return submit semantics\n     */\n    TYPE intent() default Transaction.TYPE.SUBMIT;\n\n    /**\n     * The name of the callable transaction if it should be different to the method name.\n     *\n     * @return the transaction name\n     */\n    String name() default \"\";\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/package-info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Provides annotations required for Contract implementations.\n *\n * @see org.hyperledger.fabric.contract.ContractInterface\n */\npackage org.hyperledger.fabric.contract.annotation;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/ExecutionFactory.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract.execution;\n\nimport org.hyperledger.fabric.contract.execution.impl.ContractExecutionService;\nimport org.hyperledger.fabric.contract.execution.impl.ContractInvocationRequest;\nimport org.hyperledger.fabric.contract.routing.impl.SerializerRegistryImpl;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\n\npublic class ExecutionFactory {\n    private static final ExecutionFactory INSTANCE = new ExecutionFactory();\n\n    /** @return ExecutionFactory */\n    public static ExecutionFactory getInstance() {\n        return INSTANCE;\n    }\n\n    /**\n     * @param context Chaincode Context\n     * @return Invocation request\n     */\n    public InvocationRequest createRequest(final ChaincodeStub context) {\n        return new ContractInvocationRequest(context);\n    }\n\n    /**\n     * @param serializers Instance of the serializer\n     * @return Execution Service\n     */\n    public ExecutionService createExecutionService(final SerializerRegistryImpl serializers) {\n        return new ContractExecutionService(serializers);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/ExecutionService.java",
    "content": "/*\n * Copyright 2019 IBM DTCC All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract.execution;\n\nimport org.hyperledger.fabric.contract.routing.TxFunction;\nimport org.hyperledger.fabric.shim.Chaincode;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\n\n/**\n * ExecutionService.\n *\n * <p>Service that executes {@link InvocationRequest} (wrapped Init/Invoke + extra data) using routing information\n */\n@FunctionalInterface\npublic interface ExecutionService {\n\n    /**\n     * @param txFn\n     * @param req\n     * @param stub\n     * @return Chaincode response\n     */\n    Chaincode.Response executeRequest(TxFunction txFn, InvocationRequest req, ChaincodeStub stub);\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/InvocationRequest.java",
    "content": "/*\n * Copyright 2019 IBM DTCC All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract.execution;\n\nimport java.util.List;\n\n/**\n * Invocation Request.\n *\n * <p>All information needed to find {@link org.hyperledger.fabric.contract.annotation.Contract} and invoke the request.\n */\npublic interface InvocationRequest {\n    /** */\n    String DEFAULT_NAMESPACE = \"default\";\n\n    /** @return Namespace */\n    String getNamespace();\n\n    /** @return Method */\n    String getMethod();\n\n    /** @return Args as byte array */\n    List<byte[]> getArgs();\n\n    /** @return Request */\n    String getRequestName();\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/JSONTransactionSerializer.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract.execution;\n\nimport static java.nio.charset.StandardCharsets.UTF_8;\n\nimport java.lang.reflect.Array;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.Map;\nimport java.util.Set;\nimport org.hyperledger.fabric.Logger;\nimport org.hyperledger.fabric.contract.ContractRuntimeException;\nimport org.hyperledger.fabric.contract.annotation.Serializer;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\nimport org.hyperledger.fabric.contract.routing.DataTypeDefinition;\nimport org.hyperledger.fabric.contract.routing.PropertyDefinition;\nimport org.hyperledger.fabric.contract.routing.TypeRegistry;\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\n/** Used as the default serialisation for transmission from SDK to Contract. */\n@Serializer()\n@SuppressWarnings({\n    \"PMD.GodClass\",\n    \"PMD.AvoidLiteralsInIfCondition\",\n    \"PMD.AvoidDuplicateLiterals\",\n    \"PMD.AvoidDeeplyNestedIfStmts\"\n})\npublic class JSONTransactionSerializer implements SerializerInterface {\n    private static final Logger LOGGER = Logger.getLogger(JSONTransactionSerializer.class.getName());\n    private final TypeRegistry typeRegistry = TypeRegistry.getRegistry();\n\n    /**\n     * Convert the value supplied to a byte array, according to the TypeSchema.\n     *\n     * @param value\n     * @param ts\n     * @return Byte buffer\n     */\n    @Override\n    public byte[] toBuffer(final Object value, final TypeSchema ts) {\n        LOGGER.debug(() -> \"Schema to convert is \" + ts);\n        byte[] buffer = null;\n        if (value != null) {\n            final String type = ts.getType();\n            if (type != null) {\n                switch (type) {\n                    case \"array\":\n                        final JSONArray array = normalizeArray(new JSONArray(value), ts);\n                        buffer = array.toString().getBytes(UTF_8);\n                        break;\n                    case \"string\":\n                        final String format = ts.getFormat();\n                        if (\"utin16\".equals(format)) {\n                            buffer = Character.valueOf((char) value).toString().getBytes(UTF_8);\n                        } else {\n                            buffer = ((String) value).getBytes(UTF_8);\n                        }\n                        break;\n                    case \"number\":\n                    case \"integer\":\n                    case \"boolean\":\n                    default:\n                        buffer = value.toString().getBytes(UTF_8);\n                }\n            } else {\n                // at this point we can assert that the value is\n                // representing a complex data type\n                // so we can get this from\n                // the type registry, and get the list of propertyNames\n                // it should have\n                final DataTypeDefinition dtd = this.typeRegistry.getDataType(ts);\n                final Set<String> keySet = dtd.getProperties().keySet();\n                final String[] propNames = keySet.toArray(new String[0]);\n\n                // Note: whilst the current JSON library does pretty much\n                // everything is required, this part is hard.\n                // we want to create a JSON Object based on the value,\n                // with certain property names.\n\n                // Based on the constructors available we need to have a two\n                // step process, create a JSON Object, then create the object\n                // we really want based on the propNames\n                final JSONObject obj = new JSONObject(new JSONObject(value), propNames);\n                buffer = obj.toString().getBytes(UTF_8);\n            }\n        }\n        return buffer;\n    }\n\n    /**\n     * Normalize the Array.\n     *\n     * <p>We need to take the JSON array, and if there are complex datatypes within it ensure that they don't get\n     * spurious JSON properties appearing\n     *\n     * <p>This method needs to be general so has to copy with nested arrays and with primitive and Object types\n     *\n     * @param jsonArray incoming array\n     * @param ts Schema to normalise to\n     * @return JSONArray\n     */\n    @SuppressWarnings(\"PMD.AvoidInstantiatingObjectsInLoops\")\n    private JSONArray normalizeArray(final JSONArray jsonArray, final TypeSchema ts) {\n        JSONArray normalizedArray;\n\n        // Need to work with what type of array this is\n        final TypeSchema items = ts.getItems();\n        final String type = items.getType();\n\n        if (null == type) {\n            // get the permitted propeties in the type,\n            // then loop over the array and ensure they are correct\n            final DataTypeDefinition dtd = this.typeRegistry.getDataType(items);\n            final Set<String> keySet = dtd.getProperties().keySet();\n            final String[] propNames = keySet.toArray(new String[0]);\n\n            normalizedArray = new JSONArray();\n            // array of objects\n            // iterate over said array\n            for (int i = 0; i < jsonArray.length(); i++) {\n                final JSONObject obj = new JSONObject(jsonArray.getJSONObject(i), propNames);\n                normalizedArray.put(i, obj);\n            }\n        } else if (\"array\".equals(type)) {\n            // nested arrays, get the type of what it makes up\n            // Need to loop over all elements and normalize each one\n            normalizedArray = new JSONArray();\n            for (int i = 0; i < jsonArray.length(); i++) {\n                normalizedArray.put(i, normalizeArray(jsonArray.getJSONArray(i), items));\n            }\n        } else {\n            // primitive - can return this directly\n            normalizedArray = jsonArray;\n        }\n\n        return normalizedArray;\n    }\n\n    /**\n     * Take the byte buffer and return the object as required.\n     *\n     * @param buffer Byte buffer from the wire\n     * @param ts TypeSchema representing the type\n     * @return Object created; relies on Java auto-boxing for primitives\n     */\n    @Override\n    public Object fromBuffer(final byte[] buffer, final TypeSchema ts) {\n        try {\n            final String stringData = new String(buffer, UTF_8);\n            return convert(stringData, ts);\n        } catch (InstantiationException | IllegalAccessException e) {\n            throw new ContractRuntimeException(e);\n        }\n    }\n\n    /**\n     * We need to be able to map between the primative class types and the object variants. In the case where this is\n     * needed Java auto-boxing doesn't actually help.\n     *\n     * <p>For other types the parameter is passed directly back\n     *\n     * @param primitive class for the primitive\n     * @return Class for the Object variant\n     */\n    private Class<?> mapPrimitive(final Class<?> primitive) {\n        if (primitive.isArray()) {\n            return mapArrayPrimitive(primitive);\n        }\n\n        return mapBasicPrimitive(primitive);\n    }\n\n    private Class<?> mapArrayPrimitive(final Class<?> primitive) {\n        switch (primitive.getComponentType().getName()) {\n            case \"int\":\n                return Integer[].class;\n            case \"long\":\n                return Long[].class;\n            case \"float\":\n                return Float[].class;\n            case \"double\":\n                return Double[].class;\n            case \"short\":\n                return Short[].class;\n            case \"byte\":\n                return Byte[].class;\n            case \"char\":\n                return Character[].class;\n            case \"boolean\":\n                return Boolean[].class;\n            default:\n                return primitive;\n        }\n    }\n\n    private Class<?> mapBasicPrimitive(final Class<?> primitive) {\n        switch (primitive.getName()) {\n            case \"int\":\n                return Integer.class;\n            case \"long\":\n                return Long.class;\n            case \"float\":\n                return Float.class;\n            case \"double\":\n                return Double.class;\n            case \"short\":\n                return Short.class;\n            case \"byte\":\n                return Byte.class;\n            case \"char\":\n                return Character.class;\n            case \"boolean\":\n                return Boolean.class;\n            default:\n                return primitive;\n        }\n    }\n\n    /** Internal method to do the conversion */\n    private Object convert(final String stringData, final TypeSchema ts)\n            throws IllegalAccessException, InstantiationException {\n        LOGGER.debug(() -> \"Schema to convert is \" + ts);\n\n        String type = ts.getType();\n\n        String format = null;\n        if (type == null) {\n            type = \"object\";\n            final String ref = ts.getRef();\n            format = ref.substring(ref.lastIndexOf('/') + 1);\n        }\n\n        switch (type) {\n            case \"string\":\n                return convertString(stringData, ts);\n            case \"integer\":\n                return convertInteger(stringData, ts);\n            case \"number\":\n                return convertNumber(stringData, ts);\n            case \"boolean\":\n                return Boolean.parseBoolean(stringData);\n            case \"object\":\n                return createComponentInstance(format, stringData, ts);\n            case \"array\":\n                return convertArray(stringData, ts);\n            default:\n                return null;\n        }\n    }\n\n    private Object convertArray(final String stringData, final TypeSchema ts)\n            throws IllegalAccessException, InstantiationException {\n        final JSONArray jsonArray = new JSONArray(stringData);\n        final TypeSchema itemSchema = ts.getItems();\n\n        // note here that the type has to be converted in the case of primitives\n        final Object[] data = (Object[])\n                Array.newInstance(mapPrimitive(itemSchema.getTypeClass(this.typeRegistry)), jsonArray.length());\n        for (int i = 0; i < jsonArray.length(); i++) {\n            final Object convertedData = convert(jsonArray.get(i).toString(), itemSchema);\n            data[i] = convertedData;\n        }\n\n        return data;\n    }\n\n    private Object convertNumber(final String stringData, final TypeSchema ts) {\n        if (\"float\".equals(ts.getFormat())) {\n            return Float.parseFloat(stringData);\n        }\n\n        return Double.parseDouble(stringData);\n    }\n\n    private Object convertInteger(final String stringData, final TypeSchema ts) {\n        switch (ts.getFormat()) {\n            case \"int32\":\n                return Integer.parseInt(stringData);\n            case \"int8\":\n                return Byte.parseByte(stringData);\n            case \"int16\":\n                return Short.parseShort(stringData);\n            case \"int64\":\n                return Long.parseLong(stringData);\n            default:\n                throw new IllegalArgumentException(\"Unknown format for integer \" + ts.getFormat());\n        }\n    }\n\n    private Object convertString(final String stringData, final TypeSchema ts) {\n        if (\"uint16\".equals(ts.getFormat())) {\n            return stringData.charAt(0);\n        }\n\n        return stringData;\n    }\n\n    /**\n     * Create new instance of the specificied object from the supplied JSON String.\n     *\n     * @param format Details of the format needed\n     * @param jsonString JSON string\n     * @param ts TypeSchema\n     * @return new object\n     */\n    @SuppressWarnings(\"PMD.AvoidAccessibilityAlteration\")\n    Object createComponentInstance(final String format, final String jsonString, final TypeSchema ts) {\n\n        final DataTypeDefinition dtd = this.typeRegistry.getDataType(format);\n        Object obj;\n        try {\n            obj = dtd.getTypeClass().getDeclaredConstructor().newInstance();\n        } catch (IllegalAccessException\n                | InstantiationException\n                | InvocationTargetException\n                | NoSuchMethodException e1) {\n            throw new ContractRuntimeException(\"Unable to to create new instance of type\", e1);\n        }\n\n        final JSONObject json = new JSONObject(jsonString);\n        // request validation of the type may throw an exception if validation fails\n        ts.validate(json);\n        try {\n            final Map<String, PropertyDefinition> fields = dtd.getProperties();\n            for (final PropertyDefinition prop : fields.values()) {\n                final Field f = prop.getField();\n                f.setAccessible(true);\n                final Object newValue = convert(json.get(prop.getName()).toString(), prop.getSchema());\n\n                f.set(obj, newValue);\n            }\n            return obj;\n        } catch (SecurityException\n                | IllegalArgumentException\n                | IllegalAccessException\n                | InstantiationException\n                | JSONException e) {\n            throw new ContractRuntimeException(\"Unable to convert JSON to object\", e);\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/SerializerInterface.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract.execution;\n\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\n\n/**\n * This interface allows contract developers to change the serialization mechanism. There are two scenarios where\n * instances of DataTypes are serialized.\n *\n * <p>When the objects are (logically) transferred from the Client application to the Contract resulting in a\n * transaction function being invoked. Typically this is JSON, hence a default JSON parser is provided.\n *\n * <p>The JSONTransactionSerializer can be extended if needed\n */\npublic interface SerializerInterface {\n\n    /**\n     * Convert the value supplied to a byte array, according to the TypeSchema.\n     *\n     * @param value\n     * @param ts\n     * @return buffer\n     */\n    byte[] toBuffer(Object value, TypeSchema ts);\n\n    /**\n     * Take the byte buffer and return the object as required.\n     *\n     * @param buffer Byte buffer from the wire\n     * @param ts TypeSchema representing the type\n     * @return Object created; relies on Java auto-boxing for primitives\n     */\n    Object fromBuffer(byte[] buffer, TypeSchema ts);\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/impl/ContractExecutionService.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract.execution.impl;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.logging.Logger;\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.ContractRuntimeException;\nimport org.hyperledger.fabric.contract.annotation.Serializer;\nimport org.hyperledger.fabric.contract.execution.ExecutionService;\nimport org.hyperledger.fabric.contract.execution.InvocationRequest;\nimport org.hyperledger.fabric.contract.execution.SerializerInterface;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\nimport org.hyperledger.fabric.contract.routing.ParameterDefinition;\nimport org.hyperledger.fabric.contract.routing.TxFunction;\nimport org.hyperledger.fabric.contract.routing.impl.SerializerRegistryImpl;\nimport org.hyperledger.fabric.shim.Chaincode;\nimport org.hyperledger.fabric.shim.ChaincodeException;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.hyperledger.fabric.shim.ResponseUtils;\n\npublic class ContractExecutionService implements ExecutionService {\n\n    private static final Logger LOGGER = Logger.getLogger(ContractExecutionService.class.getName());\n\n    private final SerializerRegistryImpl serializers;\n\n    /** @param serializers */\n    public ContractExecutionService(final SerializerRegistryImpl serializers) {\n        this.serializers = serializers;\n    }\n\n    /** */\n    @Override\n    public Chaincode.Response executeRequest(\n            final TxFunction txFn, final InvocationRequest req, final ChaincodeStub stub) {\n        LOGGER.fine(() -> \"Routing Request\" + txFn);\n        final TxFunction.Routing rd = txFn.getRouting();\n        Chaincode.Response response;\n\n        try {\n            final ContractInterface contractObject = rd.getContractInstance();\n            final Context context = contractObject.createContext(stub);\n\n            final List<Object> args = convertArgs(req.getArgs(), txFn);\n            args.add(0, context); // force context into 1st position, other elements move up\n\n            contractObject.beforeTransaction(context);\n            final Object value = rd.getMethod().invoke(contractObject, args.toArray());\n            contractObject.afterTransaction(context, value);\n\n            if (value == null) {\n                response = ResponseUtils.newSuccessResponse();\n            } else {\n                response = ResponseUtils.newSuccessResponse(convertReturn(value, txFn));\n            }\n\n        } catch (IllegalAccessException | InstantiationException | NoSuchMethodException e) {\n            final String message = String.format(\"Could not execute contract method: %s\", rd.toString());\n            throw new ContractRuntimeException(message, e);\n        } catch (final InvocationTargetException e) {\n            final Throwable cause = e.getCause();\n\n            if (cause instanceof ChaincodeException) {\n                response = ResponseUtils.newErrorResponse(cause);\n            } else {\n                throw new ContractRuntimeException(\"Error during contract method execution\", cause);\n            }\n        }\n\n        return response;\n    }\n\n    private byte[] convertReturn(final Object obj, final TxFunction txFn) {\n        final SerializerInterface serializer =\n                serializers.getSerializer(txFn.getRouting().getSerializerName(), Serializer.TARGET.TRANSACTION);\n        final TypeSchema ts = txFn.getReturnSchema();\n        return serializer.toBuffer(obj, ts);\n    }\n\n    private List<Object> convertArgs(final List<byte[]> stubArgs, final TxFunction txFn) {\n        final SerializerInterface serializer =\n                serializers.getSerializer(txFn.getRouting().getSerializerName(), Serializer.TARGET.TRANSACTION);\n        final List<ParameterDefinition> schemaParams = txFn.getParamsList();\n        final List<Object> args = new ArrayList<>(stubArgs.size() + 1); // allow for context as the first argument\n        for (int i = 0; i < schemaParams.size(); i++) {\n            args.add(\n                    i,\n                    serializer.fromBuffer(stubArgs.get(i), schemaParams.get(i).getSchema()));\n        }\n        return args;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/impl/ContractInvocationRequest.java",
    "content": "/*\n * Copyright 2019 IBM DTCC All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract.execution.impl;\n\nimport java.nio.charset.StandardCharsets;\nimport java.util.List;\nimport java.util.regex.Pattern;\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\nimport org.hyperledger.fabric.contract.execution.InvocationRequest;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\n\npublic final class ContractInvocationRequest implements InvocationRequest {\n    @SuppressWarnings(\"PMD.ProperLogger\") // PMD 7.12.0 gives a false positive here\n    private static final Log LOGGER = LogFactory.getLog(ContractInvocationRequest.class);\n\n    private static final Pattern NS_REGEX = Pattern.compile(\":\");\n\n    private final String namespace;\n    private final String method;\n    private final List<byte[]> args;\n\n    /** @param context */\n    @SuppressWarnings(\"PMD.AvoidLiteralsInIfCondition\")\n    public ContractInvocationRequest(final ChaincodeStub context) {\n        List<byte[]> funcAndArgs = context.getArgs();\n        if (funcAndArgs.isEmpty()) {\n            throw new IllegalArgumentException(\"Missing function name\");\n        }\n\n        final String func = new String(funcAndArgs.get(0), StandardCharsets.UTF_8);\n        LOGGER.debug(func);\n\n        final String[] funcParts = NS_REGEX.split(func);\n        if (funcParts.length == 2) {\n            namespace = funcParts[0];\n            method = funcParts[1];\n        } else {\n            namespace = DEFAULT_NAMESPACE;\n            method = funcParts[0];\n        }\n\n        args = funcAndArgs.subList(1, funcAndArgs.size());\n        if (LOGGER.isDebugEnabled()) {\n            LOGGER.debug(namespace + \" \" + method + \" \" + args);\n        }\n    }\n\n    /** */\n    @Override\n    public String getNamespace() {\n        return namespace;\n    }\n\n    /** */\n    @Override\n    public String getMethod() {\n        return method;\n    }\n\n    /** */\n    @Override\n    public List<byte[]> getArgs() {\n        return args;\n    }\n\n    /** */\n    @Override\n    public String getRequestName() {\n        return namespace + \":\" + method;\n    }\n\n    /** */\n    @Override\n    public String toString() {\n        return namespace + \":\" + method + \" @\" + Integer.toHexString(System.identityHashCode(this));\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/impl/package-info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/** */\npackage org.hyperledger.fabric.contract.execution.impl;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/package-info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/** */\npackage org.hyperledger.fabric.contract.execution;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/metadata/MetadataBuilder.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.metadata;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.Serializable;\nimport java.io.UncheckedIOException;\nimport java.net.URI;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.stream.Collectors;\nimport org.everit.json.schema.Schema;\nimport org.everit.json.schema.ValidationException;\nimport org.everit.json.schema.loader.SchemaClient;\nimport org.everit.json.schema.loader.SchemaLoader;\nimport org.everit.json.schema.loader.internal.DefaultSchemaClient;\nimport org.hyperledger.fabric.Logger;\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.Info;\nimport org.hyperledger.fabric.contract.routing.ContractDefinition;\nimport org.hyperledger.fabric.contract.routing.DataTypeDefinition;\nimport org.hyperledger.fabric.contract.routing.RoutingRegistry;\nimport org.hyperledger.fabric.contract.routing.TransactionType;\nimport org.hyperledger.fabric.contract.routing.TxFunction;\nimport org.hyperledger.fabric.contract.routing.TypeRegistry;\nimport org.json.JSONObject;\nimport org.json.JSONTokener;\n\n/**\n * Builder to assist in production of the metadata.\n *\n * <p>This class is used to build up the JSON structure to be returned as the metadata It is not a store of information,\n * rather a set of functional data to process to and from metadata json to the internal data structure\n */\n@SuppressWarnings(\"PMD.AvoidDuplicateLiterals\")\npublic final class MetadataBuilder {\n    private static final Logger LOGGER = Logger.getLogger(MetadataBuilder.class);\n\n    private static final int PADDING = 3;\n\n    // Metadata is composed of three primary sections\n    // each of which is stored in a map\n    private static Map<String, Map<String, Serializable>> contractMap = new HashMap<>();\n    private static Map<String, Object> overallInfoMap = new HashMap<>();\n    private static Map<String, Object> componentMap = new HashMap<>();\n\n    // The schema client used to load any other referenced schemas\n    private static SchemaClient schemaClient = new DefaultSchemaClient();\n\n    static final class MetadataMap<K, V> extends HashMap<K, V> {\n        private static final long serialVersionUID = 1L;\n\n        V putIfNotNull(final K key, final V value) {\n            LOGGER.info(() -> key + \" \" + value);\n            if (value != null && !value.toString().isEmpty()) {\n                return put(key, value);\n            } else {\n                return null;\n            }\n        }\n    }\n\n    private MetadataBuilder() {}\n\n    /**\n     * Validation method.\n     *\n     * @throws ValidationException if the metadata is not valid\n     */\n    public static void validate() {\n        LOGGER.info(\"Running schema test validation\");\n        final ClassLoader cl = MetadataBuilder.class.getClassLoader();\n        try (InputStream contractSchemaInputStream = cl.getResourceAsStream(\"contract-schema.json\");\n                InputStream jsonSchemaInputStream = cl.getResourceAsStream(\"json-schema-draft-04-schema.json\")) {\n            final JSONObject rawContractSchema = new JSONObject(new JSONTokener(contractSchemaInputStream));\n            final JSONObject rawJsonSchema = new JSONObject(new JSONTokener(jsonSchemaInputStream));\n            final SchemaLoader schemaLoader = SchemaLoader.builder()\n                    .schemaClient(schemaClient)\n                    .schemaJson(rawContractSchema)\n                    .registerSchemaByURI(URI.create(\"http://json-schema.org/draft-04/schema\"), rawJsonSchema)\n                    .build();\n            final Schema schema = schemaLoader.load().build();\n            schema.validate(metadata());\n\n        } catch (final IOException e) {\n            throw new UncheckedIOException(e);\n        } catch (final ValidationException e) {\n            LOGGER.error(e::getMessage);\n            e.getCausingExceptions().stream()\n                    .map(ValidationException::getMessage)\n                    .forEach(LOGGER::info);\n            LOGGER.error(MetadataBuilder::debugString);\n            throw e;\n        }\n    }\n\n    /**\n     * Setup the metadata from the found contracts.\n     *\n     * @param registry RoutingRegistry\n     * @param typeRegistry TypeRegistry\n     */\n    public static void initialize(final RoutingRegistry registry, final TypeRegistry typeRegistry) {\n        final Collection<ContractDefinition> contractDefinitions = registry.getAllDefinitions();\n        contractDefinitions.forEach(MetadataBuilder::addContract);\n\n        final Collection<DataTypeDefinition> dataTypes = typeRegistry.getAllDataTypes();\n        dataTypes.forEach(MetadataBuilder::addComponent);\n\n        // need to validate that the metadata that has been created is really valid\n        // it should be as it's been created by code, but this is a valuable double\n        // check\n        LOGGER.info(\"Validating schema created\");\n        validate();\n    }\n\n    /**\n     * Adds a component/ complex data-type.\n     *\n     * @param datatype DataTypeDefinition\n     */\n    public static void addComponent(final DataTypeDefinition datatype) {\n\n        final Map<String, Object> component = new HashMap<>();\n\n        component.put(\"$id\", datatype.getName());\n        component.put(\"type\", \"object\");\n        component.put(\"additionalProperties\", false);\n\n        final Map<String, TypeSchema> propertiesMap = datatype.getProperties().entrySet().stream()\n                .collect(Collectors.toMap(Entry::getKey, e -> e.getValue().getSchema()));\n        component.put(\"properties\", propertiesMap);\n\n        componentMap.put(datatype.getSimpleName(), component);\n    }\n\n    /**\n     * Adds a new contract to the metadata as represented by the class object.\n     *\n     * @param contractDefinition Class of the object to use as a contract\n     * @return the key that the contract class is referred to in the metadata\n     */\n    @SuppressWarnings(\"PMD.LooseCoupling\")\n    public static String addContract(final ContractDefinition contractDefinition) {\n\n        final String key = contractDefinition.getName();\n\n        final Contract annotation = contractDefinition.getAnnotation();\n\n        final Info info = annotation.info();\n        final HashMap<String, Object> infoMap = new HashMap<>();\n        infoMap.put(\"title\", info.title());\n        infoMap.put(\"description\", info.description());\n        infoMap.put(\"termsOfService\", info.termsOfService());\n\n        MetadataMap<String, String> contact = new MetadataMap<>();\n        contact.putIfNotNull(\"email\", info.contact().email());\n        contact.putIfNotNull(\"name\", info.contact().name());\n        contact.putIfNotNull(\"url\", info.contact().url());\n        infoMap.put(\"contact\", contact);\n\n        MetadataMap<String, String> license = new MetadataMap<>();\n        license.put(\"name\", info.license().name());\n        license.putIfNotNull(\"url\", info.license().url());\n        infoMap.put(\"license\", license);\n\n        infoMap.put(\"version\", info.version());\n\n        final HashMap<String, Serializable> contract = new HashMap<>();\n        contract.put(\"name\", key);\n        contract.put(\"transactions\", new ArrayList<>());\n        contract.put(\"info\", infoMap);\n\n        contractMap.put(key, contract);\n        overallInfoMap.putAll(infoMap);\n\n        final Collection<TxFunction> fns = contractDefinition.getTxFunctions();\n        fns.forEach(txFn -> addTransaction(txFn, key));\n\n        return key;\n    }\n\n    /**\n     * Adds a new transaction function to the metadata for the given contract.\n     *\n     * @param txFunction Object representing the transaction function\n     * @param contractName Name of the contract that this function belongs to\n     */\n    public static void addTransaction(final TxFunction txFunction, final String contractName) {\n        final TypeSchema transaction = new TypeSchema();\n        final TypeSchema returnSchema = txFunction.getReturnSchema();\n        if (returnSchema != null) {\n            transaction.put(\"returns\", returnSchema);\n        }\n\n        final List<TransactionType> tags = new ArrayList<>();\n        tags.add(txFunction.getType());\n        if (txFunction.getType() == TransactionType.SUBMIT) { // add deprecated tags\n            tags.add(TransactionType.INVOKE);\n        } else {\n            tags.add(TransactionType.QUERY);\n        }\n\n        final Map<String, Serializable> contract = contractMap.get(contractName);\n        @SuppressWarnings(\"unchecked\")\n        final List<Object> txs = (ArrayList<Object>) contract.get(\"transactions\");\n\n        final List<TypeSchema> paramsList = new ArrayList<>();\n        txFunction.getParamsList().forEach(pd -> {\n            final TypeSchema paramMap = pd.getSchema();\n            paramMap.put(\"name\", pd.getName());\n            paramsList.add(paramMap);\n        });\n\n        transaction.put(\"parameters\", paramsList);\n\n        if (!tags.isEmpty()) {\n            transaction.put(\"tags\", tags.toArray());\n            transaction.put(\"name\", txFunction.getName());\n            txs.add(transaction);\n        }\n    }\n\n    /**\n     * Returns the metadata as a JSON string (compact).\n     *\n     * @return metadata as String\n     */\n    public static String getMetadata() {\n        return metadata().toString();\n    }\n\n    /**\n     * Returns the metadata as a JSON string (spaced out for humans).\n     *\n     * @return metadata as a spaced out string for humans\n     */\n    public static String debugString() {\n        return metadata().toString(PADDING);\n    }\n\n    /**\n     * Create a JSONObject representing the schema.\n     *\n     * @return JSONObject of the metadata\n     */\n    private static JSONObject metadata() {\n        final Map<String, Object> metadata = new HashMap<>();\n\n        metadata.put(\"$schema\", \"https://fabric-shim.github.io/release-1.4/contract-schema.json\");\n        metadata.put(\"info\", overallInfoMap);\n        metadata.put(\"contracts\", contractMap);\n        metadata.put(\"components\", Collections.singletonMap(\"schemas\", componentMap));\n\n        return new JSONObject(metadata);\n    }\n\n    /** @return All the components indexed by name */\n    public static Map<?, ?> getComponents() {\n        return componentMap;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/metadata/TypeSchema.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract.metadata;\n\nimport java.lang.reflect.Array;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Optional;\nimport org.everit.json.schema.Schema;\nimport org.everit.json.schema.ValidationException;\nimport org.everit.json.schema.loader.SchemaLoader;\nimport org.hyperledger.fabric.Logger;\nimport org.hyperledger.fabric.contract.ContractRuntimeException;\nimport org.hyperledger.fabric.contract.routing.TypeRegistry;\nimport org.json.JSONObject;\n\n/**\n * TypeSchema.\n *\n * <p>Custom sub-type of Map that helps with the case where if there's no value then do not insert the property at all\n *\n * <p>Does not include the \"schema\" top level map\n */\n@SuppressWarnings(\"PMD.GodClass\")\npublic final class TypeSchema extends HashMap<String, Object> {\n    private static final long serialVersionUID = 1L;\n    private static final Logger LOGGER = Logger.getLogger(TypeSchema.class.getName());\n\n    private static final String SCHEMA_PROP = \"schema\";\n    private static final String TYPE_PROP = \"type\";\n    private static final String ITEMS_PROP = \"items\";\n    private static final String FORMAT_PROP = \"format\";\n    private static final String INTEGER_TYPE = \"integer\";\n\n    private Object putInternal(final String key, final Object value) {\n        if (value != null && !value.toString().isEmpty()) {\n            return put(key, value);\n        } else {\n            return null;\n        }\n    }\n\n    String putIfNotNull(final String key, final String value) {\n        return (String) this.putInternal(key, value);\n    }\n\n    String[] putIfNotNull(final String key, final String[] value) {\n        return (String[]) this.putInternal(key, value);\n    }\n\n    TypeSchema putIfNotNull(final String key, final TypeSchema value) {\n        return (TypeSchema) this.putInternal(key, value);\n    }\n\n    TypeSchema[] putIfNotNull(final String key, final TypeSchema[] value) {\n        return (TypeSchema[]) this.putInternal(key, value);\n    }\n\n    /** @return Return Type String */\n    public String getType() {\n        if (this.containsKey(SCHEMA_PROP)) {\n            final Map<?, ?> intermediateMap = (Map<?, ?>) this.get(SCHEMA_PROP);\n            return (String) intermediateMap.get(TYPE_PROP);\n        }\n        return (String) this.get(TYPE_PROP);\n    }\n\n    /** @return TypeSchema items */\n    public TypeSchema getItems() {\n        if (this.containsKey(SCHEMA_PROP)) {\n            final Map<?, ?> intermediateMap = (Map<?, ?>) this.get(SCHEMA_PROP);\n            return (TypeSchema) intermediateMap.get(ITEMS_PROP);\n        }\n        return (TypeSchema) this.get(ITEMS_PROP);\n    }\n\n    /** @return Reference */\n    public String getRef() {\n        if (this.containsKey(SCHEMA_PROP)) {\n            final Map<?, ?> intermediateMap = (Map<?, ?>) this.get(SCHEMA_PROP);\n            return (String) intermediateMap.get(\"$ref\");\n        }\n        return (String) this.get(\"$ref\");\n    }\n\n    /** @return Format */\n    public String getFormat() {\n        if (this.containsKey(SCHEMA_PROP)) {\n            final Map<?, ?> intermediateMap = (Map<?, ?>) this.get(SCHEMA_PROP);\n            return (String) intermediateMap.get(FORMAT_PROP);\n        }\n        return (String) this.get(FORMAT_PROP);\n    }\n\n    /**\n     * @param typeRegistry\n     * @return Class object\n     */\n    public Class<?> getTypeClass(final TypeRegistry typeRegistry) {\n        String type = Optional.ofNullable(getType()).orElse(\"object\");\n\n        switch (type) {\n            case \"object\":\n                return getObjectClass(typeRegistry);\n            case \"string\":\n                return getStringClass();\n            case INTEGER_TYPE:\n                return getIntegerClass();\n            case \"number\":\n                return getNumberClass();\n            case \"boolean\":\n                return boolean.class;\n            case \"array\":\n                return getArrayClass(typeRegistry);\n            default:\n                return null;\n        }\n    }\n\n    private Class<?> getArrayClass(final TypeRegistry typeRegistry) {\n        final TypeSchema typdef = this.getItems();\n        final Class<?> arrayType = typdef.getTypeClass(typeRegistry);\n        return Array.newInstance(arrayType, 0).getClass();\n    }\n\n    private Class<?> getNumberClass() {\n        switch (getFormat()) {\n            case \"double\":\n                return double.class;\n            case \"float\":\n                return float.class;\n            default:\n                throw new IllegalArgumentException(\"Unknown format for number of \" + getFormat());\n        }\n    }\n\n    private Class<?> getIntegerClass() {\n        // need to check the format\n        switch (getFormat()) {\n            case \"int8\":\n                return byte.class;\n            case \"int16\":\n                return short.class;\n            case \"int32\":\n                return int.class;\n            case \"int64\":\n                return long.class;\n            default:\n                throw new IllegalArgumentException(\"Unknown format for integer of \" + getFormat());\n        }\n    }\n\n    @SuppressWarnings(\"PMD.AvoidLiteralsInIfCondition\")\n    private Class<?> getStringClass() {\n        if (\"uint16\".equals(getFormat())) {\n            return char.class;\n        }\n        return String.class;\n    }\n\n    private Class<?> getObjectClass(final TypeRegistry typeRegistry) {\n        final String ref = this.getRef();\n        final String format = ref.substring(ref.lastIndexOf('/') + 1);\n        return typeRegistry.getDataType(format).getTypeClass();\n    }\n\n    /**\n     * Provide a mapping between the Java Language types and the OpenAPI based types.\n     *\n     * @param clz\n     * @return TypeSchema\n     */\n    @SuppressWarnings({\"PMD.ReturnEmptyCollectionRatherThanNull\", \"PMD.AvoidLiteralsInIfCondition\"})\n    public static TypeSchema typeConvert(final Class<?> clz) {\n        String className = clz.getTypeName();\n\n        if (\"void\".equals(className)) {\n            return null;\n        }\n\n        final TypeSchema result = new TypeSchema();\n        TypeSchema schema = result;\n\n        if (clz.isArray()) {\n            result.put(TYPE_PROP, \"array\");\n\n            schema = new TypeSchema();\n            final Class<?> componentClass = clz.getComponentType();\n            className = componentClass.getTypeName();\n\n            // double check the componentType\n            if (componentClass.isArray()) {\n                // nested arrays\n                result.put(ITEMS_PROP, typeConvert(componentClass));\n            } else {\n                result.put(ITEMS_PROP, schema);\n            }\n        }\n\n        updateSchemaForClass(schema, className);\n\n        return result;\n    }\n\n    @SuppressWarnings(\"PMD.CyclomaticComplexity\")\n    private static void updateSchemaForClass(final TypeSchema schema, final String className) {\n        switch (className) {\n            case \"java.lang.String\":\n                schema.put(TYPE_PROP, \"string\");\n                return;\n            case \"char\":\n            case \"java.lang.Character\":\n                schema.put(TYPE_PROP, \"string\");\n                schema.put(FORMAT_PROP, \"uint16\");\n                return;\n            case \"byte\":\n            case \"java.lang.Byte\":\n                schema.put(TYPE_PROP, INTEGER_TYPE);\n                schema.put(FORMAT_PROP, \"int8\");\n                return;\n            case \"short\":\n            case \"java.lang.Short\":\n                schema.put(TYPE_PROP, INTEGER_TYPE);\n                schema.put(FORMAT_PROP, \"int16\");\n                return;\n            case \"int\":\n            case \"java.lang.Integer\":\n                schema.put(TYPE_PROP, INTEGER_TYPE);\n                schema.put(FORMAT_PROP, \"int32\");\n                return;\n            case \"long\":\n            case \"java.lang.Long\":\n                schema.put(TYPE_PROP, INTEGER_TYPE);\n                schema.put(FORMAT_PROP, \"int64\");\n                return;\n            case \"double\":\n            case \"java.lang.Double\":\n                schema.put(TYPE_PROP, \"number\");\n                schema.put(FORMAT_PROP, \"double\");\n                return;\n            case \"float\":\n            case \"java.lang.Float\":\n                schema.put(TYPE_PROP, \"number\");\n                schema.put(FORMAT_PROP, \"float\");\n                return;\n            case \"boolean\":\n            case \"java.lang.Boolean\":\n                schema.put(TYPE_PROP, \"boolean\");\n                return;\n            default:\n                schema.put(\"$ref\", \"#/components/schemas/\" + className.substring(className.lastIndexOf('.') + 1));\n        }\n    }\n\n    /**\n     * Validates the object against this schema.\n     *\n     * @param obj\n     */\n    public void validate(final JSONObject obj) {\n        // get the components bit of the main metadata\n\n        final JSONObject toValidate = new JSONObject();\n        toValidate.put(\"prop\", obj);\n\n        JSONObject schemaJSON;\n        if (this.containsKey(SCHEMA_PROP)) {\n            schemaJSON = new JSONObject((Map) this.get(SCHEMA_PROP));\n        } else {\n            schemaJSON = new JSONObject(this);\n        }\n\n        final JSONObject rawSchema = new JSONObject();\n        rawSchema.put(\"properties\", new JSONObject().put(\"prop\", schemaJSON));\n        rawSchema.put(\"components\", new JSONObject().put(\"schemas\", MetadataBuilder.getComponents()));\n        final Schema schema = SchemaLoader.load(rawSchema);\n        try {\n            schema.validate(toValidate);\n        } catch (final ValidationException e) {\n            final StringBuilder sb = new StringBuilder(\"Validation Errors::\");\n            e.getCausingExceptions().stream()\n                    .map(ValidationException::getMessage)\n                    .forEach(sb::append);\n            String message = sb.toString();\n            LOGGER.info(message);\n            throw new ContractRuntimeException(message, e);\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/metadata/package-info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/** */\npackage org.hyperledger.fabric.contract.metadata;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/package-info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Provides interfaces and classes to support the contract programming model.\n *\n * <p>The {@link org.hyperledger.fabric.contract} package implements the Fabric programming model as described in the <a\n * href= \"https://hyperledger-fabric.readthedocs.io/en/latest/developapps/developing_applications.html\">Developing\n * Applications</a> chapter of the Fabric documentation.\n *\n * <p>The main interface to implement is {@link org.hyperledger.fabric.contract.ContractInterface}\n */\npackage org.hyperledger.fabric.contract;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/ContractDefinition.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract.routing;\n\nimport java.lang.reflect.Method;\nimport java.util.Collection;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.annotation.Contract;\n\n/**\n * Definition of the Contract\n *\n * <p>A data structure that represents the contract that will be executed in the chaincode. Primarily has\n *\n * <p>Name - either defined by the Contract annotation or the Class name (can be referred to as Namespace) Default - is\n * the default contract (defined by the Default annotation) TxFunctions in this contract do not need the name prefix\n * when invoked TxFunctions - the transaction functions defined in this contract\n *\n * <p>Will embedded the ContractInterface instance, as well as the annotation itself, and the routing for any tx\n * function that is unknown\n */\npublic interface ContractDefinition {\n\n    /** @return the fully qualified name of the Contract */\n    String getName();\n\n    /** @return Complete collection of all the transaction functions in this contract */\n    Collection<TxFunction> getTxFunctions();\n\n    /** @return Object reference to the instantiated object that is 'the contract' */\n    Class<? extends ContractInterface> getContractImpl();\n\n    /**\n     * @param m The java.lang.reflect object that is the method that is a tx function\n     * @return TxFunction object representing this method\n     */\n    TxFunction addTxFunction(Method m);\n\n    /** @return if this is contract is the default one or not */\n    boolean isDefault();\n\n    /**\n     * @param method name to be returned\n     * @return TxFunction that represents this requested method\n     */\n    TxFunction getTxFunction(String method);\n\n    /**\n     * @param method name to be checked\n     * @return true if this txFunction exists or not\n     */\n    boolean hasTxFunction(String method);\n\n    /** @return The TxFunction to be used for this contract in case of unknown request */\n    TxFunction getUnknownRoute();\n\n    /** @return Underlying raw annotation */\n    Contract getAnnotation();\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/DataTypeDefinition.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing;\n\nimport java.util.Map;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\n\npublic interface DataTypeDefinition {\n\n    /** @return String */\n    String getName();\n\n    /** @return Map of String to PropertyDefinitions */\n    Map<String, PropertyDefinition> getProperties();\n\n    /** @return String */\n    String getSimpleName();\n\n    /** @return Class object of the type */\n    Class<?> getTypeClass();\n\n    /** @return TypeSchema */\n    TypeSchema getSchema();\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/ParameterDefinition.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing;\n\nimport java.lang.reflect.Parameter;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\n\npublic interface ParameterDefinition {\n\n    /** @return Class type of the parameter */\n    Class<?> getTypeClass();\n\n    /** @return TypeSchema of the parameter */\n    TypeSchema getSchema();\n\n    /** @return Parameter */\n    Parameter getParameter();\n\n    /** @return name of the parameter */\n    String getName();\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/PropertyDefinition.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing;\n\nimport java.lang.reflect.Field;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\n\npublic interface PropertyDefinition {\n\n    /** @return Class of the Property */\n    Class<?> getTypeClass();\n\n    /** @return TypeSchema */\n    TypeSchema getSchema();\n\n    /** @return Field */\n    Field getField();\n\n    /** @return Name of the property */\n    String getName();\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/RoutingRegistry.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing;\n\nimport java.util.Collection;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.execution.InvocationRequest;\n\npublic interface RoutingRegistry {\n\n    /**\n     * Add a new contract definition based on the class object located.\n     *\n     * @param clz Class Object to process into a ContractDefinition\n     * @return ContractDefinition Instance\n     */\n    ContractDefinition addNewContract(Class<ContractInterface> clz);\n\n    /**\n     * Based on the Invocation Request, can we create a route for this?\n     *\n     * @param request\n     * @return ture/false\n     */\n    boolean containsRoute(InvocationRequest request);\n\n    /**\n     * Get the route for invocation request.\n     *\n     * @param request\n     * @return Routing obect\n     */\n    TxFunction.Routing getRoute(InvocationRequest request);\n\n    /**\n     * Get the txFunction that matches the routing request.\n     *\n     * @param request\n     * @return Transaction Function\n     */\n    TxFunction getTxFn(InvocationRequest request);\n\n    /**\n     * Get the contract that matches the supplied name.\n     *\n     * @param name\n     * @return Contract Definition\n     */\n    ContractDefinition getContract(String name);\n\n    /**\n     * Returns all the ContractDefinitions for this registry.\n     *\n     * @return Collection of all definitions\n     */\n    Collection<ContractDefinition> getAllDefinitions();\n\n    /**\n     * Locate all the contracts in this chaincode.\n     *\n     * @param typeRegistry\n     */\n    void findAndSetContracts(TypeRegistry typeRegistry);\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/TransactionType.java",
    "content": "/*\n * Copyright 2019 IBM DTCC All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing;\n\npublic enum TransactionType {\n    /** */\n    INVOKE, // deprecated\n    /** */\n    QUERY, // deprecated\n    /** */\n    DEFAULT, // deprecated\n    /** */\n    SUBMIT,\n    /** */\n    EVALUATE\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/TxFunction.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.List;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\n\npublic interface TxFunction {\n\n    interface Routing {\n        /**\n         * Method to route calls to the transaction function.\n         *\n         * @return a method.\n         */\n        Method getMethod();\n\n        /**\n         * The associated contract class.\n         *\n         * @return a contract class.\n         */\n        Class<? extends ContractInterface> getContractClass();\n\n        /**\n         * The associated contract instance.\n         *\n         * @return a contract.\n         * @throws IllegalAccessException\n         * @throws InstantiationException\n         * @throws InvocationTargetException\n         * @throws NoSuchMethodException\n         */\n        ContractInterface getContractInstance()\n                throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException;\n\n        /**\n         * Name of the serializer used for the transaction function.\n         *\n         * @return a serializer name.\n         */\n        String getSerializerName();\n    }\n\n    /** @return is this tx to be called when request fn is unknown */\n    boolean isUnknownTx();\n\n    /** @param unknown true if the transaction is to be called when the request fn is unknown; otherwise false. */\n    void setUnknownTx(boolean unknown);\n\n    /** @return Name */\n    String getName();\n\n    /** @return Routing object */\n    Routing getRouting();\n\n    /** @return Class of the return type */\n    Class<?> getReturnType();\n\n    /** @return Parameter array */\n    java.lang.reflect.Parameter[] getParameters();\n\n    /** @return Submit or Evaluate */\n    TransactionType getType();\n\n    /** @param returnSchema */\n    void setReturnSchema(TypeSchema returnSchema);\n\n    /** @return TypeSchema of the return type */\n    TypeSchema getReturnSchema();\n\n    /** @param list */\n    void setParameterDefinitions(List<ParameterDefinition> list);\n\n    /** @return List of parameters */\n    List<ParameterDefinition> getParamsList();\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/TypeRegistry.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing;\n\nimport java.util.Collection;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\nimport org.hyperledger.fabric.contract.routing.impl.TypeRegistryImpl;\n\npublic interface TypeRegistry {\n\n    /** @return TypeRegistry */\n    static TypeRegistry getRegistry() {\n        return TypeRegistryImpl.getInstance();\n    }\n\n    /** @param dtd */\n    void addDataType(DataTypeDefinition dtd);\n\n    /** @param cl */\n    void addDataType(Class<?> cl);\n\n    /**\n     * @param name\n     * @return DataTypeDefinition\n     */\n    DataTypeDefinition getDataType(String name);\n\n    /**\n     * @param schema\n     * @return DataTypeDefinition\n     */\n    DataTypeDefinition getDataType(TypeSchema schema);\n\n    /** @return All datatypes */\n    Collection<DataTypeDefinition> getAllDataTypes();\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/impl/ContractDefinitionImpl.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing.impl;\n\nimport java.lang.reflect.Method;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.Map;\nimport org.hyperledger.fabric.Logger;\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.ContractRuntimeException;\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.Default;\nimport org.hyperledger.fabric.contract.routing.ContractDefinition;\nimport org.hyperledger.fabric.contract.routing.TxFunction;\n\n/**\n * Implementation of the ContractDefinition.\n *\n * <p>Contains information about the contract, including transaction functions and unknown transaction routing\n */\npublic final class ContractDefinitionImpl implements ContractDefinition {\n    private static final Logger LOGGER = Logger.getLogger(ContractDefinitionImpl.class);\n\n    private final Map<String, TxFunction> txFunctions = new HashMap<>();\n    private final String name;\n    private final boolean isDefault;\n    private final Class<? extends ContractInterface> contractClz;\n    private final Contract contractAnnotation;\n    private final TxFunction unknownTx;\n\n    /** @param cl */\n    public ContractDefinitionImpl(final Class<? extends ContractInterface> cl) {\n\n        final Contract annotation = cl.getAnnotation(Contract.class);\n        LOGGER.debug(() -> \"Class Contract Annotation: \" + annotation);\n\n        final String annotationName = annotation.name();\n\n        if (annotationName == null || annotationName.isEmpty()) {\n            this.name = cl.getSimpleName();\n        } else {\n            this.name = annotationName;\n        }\n\n        isDefault = (cl.getAnnotation(Default.class) != null);\n        contractAnnotation = cl.getAnnotation(Contract.class);\n        contractClz = cl;\n\n        try {\n            final Method m = cl.getMethod(\"unknownTransaction\", Context.class);\n            unknownTx = new TxFunctionImpl(m, this);\n            unknownTx.setUnknownTx(true);\n        } catch (NoSuchMethodException | SecurityException e) {\n            final ContractRuntimeException cre =\n                    new ContractRuntimeException(\"Failure to find unknownTransaction method\", e);\n            LOGGER.severe(() -> LOGGER.formatError(cre));\n            throw cre;\n        }\n\n        LOGGER.info(() -> \"Found class: \" + cl.getCanonicalName());\n        LOGGER.debug(() -> \"Namespace: \" + this.name);\n    }\n\n    @Override\n    public String getName() {\n        return name;\n    }\n\n    @Override\n    public Collection<TxFunction> getTxFunctions() {\n        return txFunctions.values();\n    }\n\n    @Override\n    public Class<? extends ContractInterface> getContractImpl() {\n        return contractClz;\n    }\n\n    @Override\n    public TxFunction addTxFunction(final Method m) {\n        LOGGER.debug(() -> \"Adding method \" + m.getName());\n        final TxFunction txFn = new TxFunctionImpl(m, this);\n        final TxFunction previousTxnFn = txFunctions.put(txFn.getName(), txFn);\n        if (previousTxnFn != null) {\n            final String message = String.format(\"Duplicate transaction method %s\", previousTxnFn.getName());\n            final ContractRuntimeException cre = new ContractRuntimeException(message);\n            LOGGER.severe(() -> LOGGER.formatError(cre));\n            throw cre;\n        }\n        return txFn;\n    }\n\n    @Override\n    public boolean isDefault() {\n        return isDefault;\n    }\n\n    @Override\n    public TxFunction getTxFunction(final String method) {\n        return txFunctions.get(method);\n    }\n\n    @Override\n    public boolean hasTxFunction(final String method) {\n        return txFunctions.containsKey(method);\n    }\n\n    @Override\n    public TxFunction getUnknownRoute() {\n        return unknownTx;\n    }\n\n    @Override\n    public Contract getAnnotation() {\n        return this.contractAnnotation;\n    }\n\n    @Override\n    public String toString() {\n        return name + \":\" + txFunctions + \" @\" + Integer.toHexString(System.identityHashCode(this));\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/impl/DataTypeDefinitionImpl.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing.impl;\n\nimport java.lang.reflect.Field;\nimport java.util.HashMap;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.stream.Stream;\nimport org.hyperledger.fabric.contract.annotation.Property;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\nimport org.hyperledger.fabric.contract.routing.DataTypeDefinition;\nimport org.hyperledger.fabric.contract.routing.PropertyDefinition;\n\npublic final class DataTypeDefinitionImpl implements DataTypeDefinition {\n\n    private final Map<String, PropertyDefinition> properties = new HashMap<>();\n    private final String name;\n    private final String simpleName;\n    private final Class<?> clazz;\n\n    /** @param componentClass */\n    @SuppressWarnings(\"PMD.AvoidInstantiatingObjectsInLoops\")\n    public DataTypeDefinitionImpl(final Class<?> componentClass) {\n        this.clazz = componentClass;\n        this.name = componentClass.getName();\n        this.simpleName = componentClass.getSimpleName();\n        // given this class extract the property elements\n        final Field[] fields = componentClass.getDeclaredFields();\n\n        for (final Field f : fields) {\n            final Property propAnnotation = f.getAnnotation(Property.class);\n            if (propAnnotation != null) {\n                final TypeSchema ts = TypeSchema.typeConvert(f.getType());\n\n                // array of strings, \"a\",\"b\",\"c\",\"d\" to become map of {a:b}, {c:d}\n                final String[] userSupplied = propAnnotation.schema();\n                for (int i = 0; i < userSupplied.length; i += 2) {\n                    final String userKey = userSupplied[i];\n                    Object userValue;\n                    switch (userKey.toLowerCase(Locale.getDefault())) {\n                        case \"title\":\n                        case \"pattern\":\n                            userValue = userSupplied[i + 1];\n                            break;\n                        case \"uniqueitems\":\n                            userValue = Boolean.parseBoolean(userSupplied[i + 1]);\n                            break;\n                        case \"required\":\n                        case \"enum\":\n                            userValue = Stream.of(userSupplied[i + 1].split(\",\"))\n                                    .map(String::trim)\n                                    .toArray(String[]::new);\n                            break;\n                        default:\n                            userValue = Integer.parseInt(userSupplied[i + 1]);\n                            break;\n                    }\n                    ts.put(userKey, userValue);\n                }\n\n                final PropertyDefinition propDef = new PropertyDefinitionImpl(f.getName(), f.getClass(), ts, f);\n                this.properties.put(f.getName(), propDef);\n            }\n        }\n    }\n\n    @Override\n    public Class<?> getTypeClass() {\n        return this.clazz;\n    }\n\n    @Override\n    public TypeSchema getSchema() {\n        return TypeSchema.typeConvert(this.clazz);\n    }\n\n    /*\n     * (non-Javadoc)\n     *\n     * @see org.hyperledger.fabric.contract.routing.DataTypeDefinition#getName()\n     */\n    @Override\n    public String getName() {\n        return this.name;\n    }\n\n    /*\n     * (non-Javadoc)\n     *\n     * @see\n     * org.hyperledger.fabric.contract.routing.DataTypeDefinition#getProperties()\n     */\n    @Override\n    public Map<String, PropertyDefinition> getProperties() {\n        return properties;\n    }\n\n    /*\n     * (non-Javadoc)\n     *\n     * @see\n     * org.hyperledger.fabric.contract.routing.DataTypeDefinition#getSimpleName()\n     */\n    @Override\n    public String getSimpleName() {\n        return simpleName;\n    }\n\n    @Override\n    public String toString() {\n        return this.simpleName + \" \" + properties;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/impl/ParameterDefinitionImpl.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract.routing.impl;\n\nimport java.lang.reflect.Parameter;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\nimport org.hyperledger.fabric.contract.routing.ParameterDefinition;\n\npublic final class ParameterDefinitionImpl implements ParameterDefinition {\n\n    private final Class<?> typeClass;\n    private final TypeSchema schema;\n    private final Parameter parameter;\n    private final String name;\n\n    /**\n     * @param name\n     * @param typeClass\n     * @param schema\n     * @param p\n     */\n    public ParameterDefinitionImpl(\n            final String name, final Class<?> typeClass, final TypeSchema schema, final Parameter p) {\n        this.typeClass = typeClass;\n        this.schema = schema;\n        this.parameter = p;\n        this.name = name;\n    }\n\n    @Override\n    public Class<?> getTypeClass() {\n        return this.typeClass;\n    }\n\n    @Override\n    public TypeSchema getSchema() {\n        return this.schema;\n    }\n\n    @Override\n    public Parameter getParameter() {\n        return this.parameter;\n    }\n\n    @Override\n    public String getName() {\n        return this.name;\n    }\n\n    @Override\n    public String toString() {\n        return this.name + \"-\" + this.typeClass + \"-\" + this.schema + \"-\" + this.parameter;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/impl/PropertyDefinitionImpl.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract.routing.impl;\n\nimport java.lang.reflect.Field;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\nimport org.hyperledger.fabric.contract.routing.PropertyDefinition;\n\npublic final class PropertyDefinitionImpl implements PropertyDefinition {\n\n    private final Class<?> typeClass;\n    private final TypeSchema schema;\n    private final Field field;\n    private final String name;\n\n    /**\n     * @param name\n     * @param typeClass\n     * @param schema\n     * @param f\n     */\n    public PropertyDefinitionImpl(final String name, final Class<?> typeClass, final TypeSchema schema, final Field f) {\n        this.typeClass = typeClass;\n        this.schema = schema;\n        this.field = f;\n        this.name = name;\n    }\n\n    @Override\n    public Class<?> getTypeClass() {\n        return this.typeClass;\n    }\n\n    @Override\n    public TypeSchema getSchema() {\n        return this.schema;\n    }\n\n    @Override\n    public Field getField() {\n        return this.field;\n    }\n\n    @Override\n    public String getName() {\n        return this.name;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/impl/RoutingRegistryImpl.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing.impl;\n\nimport io.github.classgraph.ClassGraph;\nimport io.github.classgraph.ClassInfo;\nimport io.github.classgraph.ScanResult;\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport org.hyperledger.fabric.Logger;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.ContractRuntimeException;\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.DataType;\nimport org.hyperledger.fabric.contract.annotation.Transaction;\nimport org.hyperledger.fabric.contract.execution.InvocationRequest;\nimport org.hyperledger.fabric.contract.routing.ContractDefinition;\nimport org.hyperledger.fabric.contract.routing.RoutingRegistry;\nimport org.hyperledger.fabric.contract.routing.TxFunction;\nimport org.hyperledger.fabric.contract.routing.TypeRegistry;\n\n/**\n * Registry to hold permit access to the routing definitions. This is the primary internal data structure to permit\n * access to information about the contracts, and their transaction functions.\n *\n * <p>Contracts are added, and processed. At runtime, this can then be accessed to locate a specific 'Route' that can be\n * handed off to the ExecutionService\n */\npublic final class RoutingRegistryImpl implements RoutingRegistry {\n    private static Logger logger = Logger.getLogger(RoutingRegistryImpl.class);\n\n    private final Map<String, ContractDefinition> contracts = new HashMap<>();\n\n    /*\n     * (non-Javadoc)\n     *\n     * @see\n     * org.hyperledger.fabric.contract.routing.RoutingRegistry#addNewContract(java.\n     * lang.Class)\n     */\n    @Override\n    public ContractDefinition addNewContract(final Class<ContractInterface> clz) {\n        logger.debug(() -> \"Adding new Contract Class \" + clz.getCanonicalName());\n        ContractDefinition contract;\n        contract = new ContractDefinitionImpl(clz);\n\n        // index this by the full qualified name\n        contracts.put(contract.getName(), contract);\n        if (contract.isDefault()) {\n            contracts.put(InvocationRequest.DEFAULT_NAMESPACE, contract);\n        }\n\n        logger.debug(() -> \"Put new contract in under name \" + contract.getName());\n        return contract;\n    }\n\n    /*\n     * (non-Javadoc)\n     *\n     * @see\n     * org.hyperledger.fabric.contract.routing.RoutingRegistry#containsRoute(org.\n     * hyperledger.fabric.contract.execution.InvocationRequest)\n     */\n    @Override\n    public boolean containsRoute(final InvocationRequest request) {\n        if (contracts.containsKey(request.getNamespace())) {\n            final ContractDefinition cd = contracts.get(request.getNamespace());\n\n            if (cd.hasTxFunction(request.getMethod())) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /*\n     * (non-Javadoc)\n     *\n     * @see org.hyperledger.fabric.contract.routing.RoutingRegistry#getRoute(org.\n     * hyperledger.fabric.contract.execution.InvocationRequest)\n     */\n    @Override\n    public TxFunction.Routing getRoute(final InvocationRequest request) {\n        final TxFunction txFunction = contracts.get(request.getNamespace()).getTxFunction(request.getMethod());\n        return txFunction.getRouting();\n    }\n\n    @Override\n    public TxFunction getTxFn(final InvocationRequest request) {\n        return contracts.get(request.getNamespace()).getTxFunction(request.getMethod());\n    }\n\n    /*\n     * (non-Javadoc)\n     *\n     * @see\n     * org.hyperledger.fabric.contract.routing.RoutingRegistry#getContract(java.lang\n     * .String)\n     */\n    @Override\n    public ContractDefinition getContract(final String namespace) {\n        final ContractDefinition contract = contracts.get(namespace);\n\n        if (contract == null) {\n            throw new ContractRuntimeException(\"Undefined contract called\");\n        }\n\n        return contract;\n    }\n\n    /*\n     * (non-Javadoc)\n     *\n     * @see\n     * org.hyperledger.fabric.contract.routing.RoutingRegistry#getAllDefinitions()\n     */\n    @Override\n    public Collection<ContractDefinition> getAllDefinitions() {\n        return contracts.values();\n    }\n\n    /*\n     * (non-Javadoc)\n     *\n     * @see\n     * org.hyperledger.fabric.contract.routing.RoutingRegistry#findAndSetContracts()\n     */\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public void findAndSetContracts(final TypeRegistry typeRegistry) {\n\n        // Find all classes that are valid contract or data type instances.\n        final ClassGraph classGraph = new ClassGraph().enableClassInfo().enableAnnotationInfo();\n        final List<Class<ContractInterface>> contractClasses = new ArrayList<>();\n        final List<Class<?>> dataTypeClasses = new ArrayList<>();\n        try (ScanResult scanResult = classGraph.scan()) {\n            for (final ClassInfo classInfo : scanResult.getClassesWithAnnotation(Contract.class.getCanonicalName())) {\n                logger.debug(() -> \"Found class with contract annotation: \" + classInfo.getName());\n                try {\n                    final Class<?> contractClass = classInfo.loadClass();\n                    logger.debug(\"Loaded class\");\n                    final Contract annotation = contractClass.getAnnotation(Contract.class);\n                    if (annotation == null) {\n                        // Since we check by name above, it makes sense to check it's actually\n                        // compatible,\n                        // and not some random class with the same name.\n                        logger.debug(\"Class does not have compatible contract annotation\");\n                    } else if (ContractInterface.class.isAssignableFrom(contractClass)) {\n                        logger.debug(\"Class is assignable from ContractInterface\");\n                        contractClasses.add((Class<ContractInterface>) contractClass);\n                    } else {\n                        logger.debug(\"Class is not assignable from ContractInterface\");\n                    }\n                } catch (final IllegalArgumentException e) {\n                    logger.debug(() -> \"Failed to load class: \" + e);\n                }\n            }\n            for (final ClassInfo classInfo : scanResult.getClassesWithAnnotation(DataType.class.getCanonicalName())) {\n                logger.debug(() -> \"Found class with data type annotation: \" + classInfo.getName());\n                try {\n                    final Class<?> dataTypeClass = classInfo.loadClass();\n                    logger.debug(\"Loaded class\");\n                    final DataType annotation = dataTypeClass.getAnnotation(DataType.class);\n                    if (annotation == null) {\n                        // Since we check by name above, it makes sense to check it's actually\n                        // compatible,\n                        // and not some random class with the same name.\n                        logger.debug(\"Class does not have compatible data type annotation\");\n                    } else {\n                        logger.debug(\"Class has compatible data type annotation\");\n                        dataTypeClasses.add(dataTypeClass);\n                    }\n                } catch (final IllegalArgumentException e) {\n                    logger.debug(() -> \"Failed to load class: \" + e);\n                }\n            }\n        }\n\n        // store the contracts in the internal data structures\n        addContracts(contractClasses);\n\n        // now need to look for the data types have been set with the\n        dataTypeClasses.forEach(typeRegistry::addDataType);\n    }\n\n    private void addContracts(final List<Class<ContractInterface>> contractClasses) {\n        // set to ensure that we don't scan the same class twice\n        final Set<String> seenClass = new HashSet<>();\n\n        // loop over all the classes that have the Contract annotation\n        for (final Class<ContractInterface> contractClass : contractClasses) {\n            final String className = contractClass.getCanonicalName();\n            if (!seenClass.contains(className)) {\n                final ContractDefinition contract = addNewContract(contractClass);\n\n                logger.debug(\"Searching annotated methods\");\n                for (final Method m : contractClass.getMethods()) {\n                    if (m.getAnnotation(Transaction.class) != null) {\n                        logger.debug(() -> \"Found annotated method \" + m.getName());\n\n                        contract.addTxFunction(m);\n                    }\n                }\n\n                seenClass.add(className);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/impl/SerializerRegistryImpl.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing.impl;\n\nimport io.github.classgraph.ClassGraph;\nimport io.github.classgraph.ClassInfo;\nimport io.github.classgraph.ScanResult;\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Set;\nimport org.hyperledger.fabric.Logger;\nimport org.hyperledger.fabric.contract.annotation.Serializer;\nimport org.hyperledger.fabric.contract.execution.SerializerInterface;\n\n/**\n * Registry to hold permit access to the serializer implementations.\n *\n * <p>It holds the serializers that have been defined. JSONTransactionSerializer is the default.\n */\npublic class SerializerRegistryImpl {\n    private static final Logger LOGGER = Logger.getLogger(SerializerRegistryImpl.class);\n\n    private static final Class<Serializer> ANNOTATION_CLASS = Serializer.class;\n\n    // Could index these by name and or type.\n    private final Map<String, SerializerInterface> contents = new HashMap<>();\n\n    /**\n     * Get a Serializer for the matching fully qualified classname, and the Target.\n     *\n     * @param name fully qualified classname\n     * @param target the intended target of the serializer\n     * @return Serializer instance\n     */\n    public SerializerInterface getSerializer(final String name, final Serializer.TARGET target) {\n        final String key = name + \":\" + target;\n        return contents.get(key);\n    }\n\n    private void add(final String name, final Serializer.TARGET target, final Class<?> clazz)\n            throws InstantiationException, IllegalAccessException {\n        LOGGER.debug(() -> \"Adding new Class \" + clazz.getCanonicalName() + \" for \" + target);\n        final String key = name + \":\" + target;\n        try {\n            final SerializerInterface newObj =\n                    (SerializerInterface) clazz.getDeclaredConstructor().newInstance();\n            this.contents.put(key, newObj);\n        } catch (InvocationTargetException | NoSuchMethodException e) {\n            InstantiationException wrapper = new InstantiationException(\n                    \"Exception constructing \" + clazz.getCanonicalName() + \": \" + e.getMessage());\n            wrapper.addSuppressed(e);\n            throw wrapper;\n        }\n    }\n\n    /**\n     * Find all the serializers that have been defined.\n     *\n     * @see org.hyperledger.fabric.contract.routing.RoutingRegistry#findAndSetContracts(TypeRegistry)\n     * @throws IllegalAccessException\n     * @throws InstantiationException\n     */\n    public void findAndSetContents() throws InstantiationException, IllegalAccessException {\n\n        final ClassGraph classGraph = new ClassGraph().enableClassInfo().enableAnnotationInfo();\n\n        // set to ensure that we don't scan the same class twice\n        final Set<String> seenClass = new HashSet<>();\n\n        try (ScanResult scanResult = classGraph.scan()) {\n            for (final ClassInfo classInfo : scanResult.getClassesWithAnnotation(ANNOTATION_CLASS.getCanonicalName())) {\n                LOGGER.debug(() -> \"Found class with contract annotation: \" + classInfo.getName());\n\n                final Class<?> cls = classInfo.loadClass();\n                LOGGER.debug(\"Loaded class\");\n\n                final String className = cls.getCanonicalName();\n                if (!seenClass.contains(className)) {\n                    seenClass.add(className);\n                    this.add(className, Serializer.TARGET.TRANSACTION, cls);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/impl/TxFunctionImpl.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing.impl;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Parameter;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport org.hyperledger.fabric.Logger;\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.ContractRuntimeException;\nimport org.hyperledger.fabric.contract.annotation.Property;\nimport org.hyperledger.fabric.contract.annotation.Transaction;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\nimport org.hyperledger.fabric.contract.routing.ContractDefinition;\nimport org.hyperledger.fabric.contract.routing.ParameterDefinition;\nimport org.hyperledger.fabric.contract.routing.TransactionType;\nimport org.hyperledger.fabric.contract.routing.TxFunction;\n\npublic final class TxFunctionImpl implements TxFunction {\n    private static final Logger LOGGER = Logger.getLogger(TxFunctionImpl.class);\n\n    private final Method method;\n    private String name;\n    private TransactionType type;\n    private final Routing routing;\n    private TypeSchema returnSchema;\n    private List<ParameterDefinition> paramsList;\n    private boolean isUnknownTx;\n\n    public static final class RoutingImpl implements Routing {\n\n        private final Method method;\n        private final Class<? extends ContractInterface> clazz;\n        private final String serializerName;\n\n        /**\n         * @param method\n         * @param contract\n         */\n        public RoutingImpl(final Method method, final ContractDefinition contract) {\n            this.method = method;\n            this.clazz = contract.getContractImpl();\n            this.serializerName = contract.getAnnotation().transactionSerializer();\n        }\n\n        @Override\n        public Method getMethod() {\n            return method;\n        }\n\n        @Override\n        public Class<? extends ContractInterface> getContractClass() {\n            return clazz;\n        }\n\n        @Override\n        public ContractInterface getContractInstance()\n                throws IllegalAccessException, InstantiationException, InvocationTargetException,\n                        NoSuchMethodException {\n            return clazz.getDeclaredConstructor().newInstance();\n        }\n\n        @Override\n        public String toString() {\n            return method.getName() + \":\" + clazz.getCanonicalName();\n        }\n\n        @Override\n        public String getSerializerName() {\n            return serializerName;\n        }\n    }\n\n    /**\n     * New TxFunction Definition Impl.\n     *\n     * @param m Reflect method object\n     * @param contract ContractDefinition this is part of\n     */\n    public TxFunctionImpl(final Method m, final ContractDefinition contract) {\n\n        this.method = m;\n        if (m.getAnnotation(Transaction.class) != null) {\n            LOGGER.debug(() -> \"Found Transaction method: \" + m.getName());\n            if (m.getAnnotation(Transaction.class).intent() == Transaction.TYPE.SUBMIT) {\n                this.type = TransactionType.SUBMIT;\n            } else {\n                this.type = TransactionType.EVALUATE;\n            }\n\n            final String txnName = m.getAnnotation(Transaction.class).name();\n            if (!txnName.isEmpty()) {\n                this.name = txnName;\n            }\n        }\n\n        if (name == null) {\n            this.name = m.getName();\n        }\n\n        // create the routing object that defines how to get the data to the transaction\n        // function.\n        this.routing = new RoutingImpl(m, contract);\n\n        // set the return schema\n        this.returnSchema = TypeSchema.typeConvert(m.getReturnType());\n\n        // parameter processing\n        this.paramsList = buildParameters(m);\n    }\n\n    private List<ParameterDefinition> buildParameters(final Method m) {\n        Parameter[] params = m.getParameters();\n        // validate the first one is a context object\n        if (params.length == 0) {\n            throw new ContractRuntimeException(\"First argument should be of type Context\");\n        }\n        if (!Context.class.isAssignableFrom(params[0].getType())) {\n            throw new ContractRuntimeException(\n                    \"First argument should be of type Context \" + m.getName() + \" \" + params[0].getType());\n        }\n\n        // FUTURE: if ever the method of creating the instance where to change,\n        // the routing could be changed here, a different implementation could be made\n        // here encapsulating the change. eg use an annotation to define where the\n        // context goes\n\n        return Arrays.stream(params)\n                .skip(1)\n                .map(TxFunctionImpl::newParameterDefinition)\n                .collect(Collectors.toList());\n    }\n\n    private static ParameterDefinitionImpl newParameterDefinition(final Parameter parameter) {\n        final TypeSchema paramMap = new TypeSchema();\n        final TypeSchema schema = TypeSchema.typeConvert(parameter.getType());\n\n        final Property annotation = parameter.getAnnotation(Property.class);\n        if (annotation != null) {\n            final String[] userSupplied = annotation.schema();\n            for (int i = 0; i < userSupplied.length; i += 2) {\n                schema.put(userSupplied[i], userSupplied[i + 1]);\n            }\n        }\n\n        paramMap.put(\"name\", parameter.getName());\n        paramMap.put(\"schema\", schema);\n        return new ParameterDefinitionImpl(parameter.getName(), parameter.getClass(), paramMap, parameter);\n    }\n\n    @Override\n    public String getName() {\n        return name;\n    }\n\n    @Override\n    public Routing getRouting() {\n        return this.routing;\n    }\n\n    @Override\n    public Class<?> getReturnType() {\n        return method.getReturnType();\n    }\n\n    @Override\n    public Parameter[] getParameters() {\n        return method.getParameters();\n    }\n\n    @Override\n    public TransactionType getType() {\n        return this.type;\n    }\n\n    @Override\n    public String toString() {\n        return name + \" @\" + Integer.toHexString(System.identityHashCode(this));\n    }\n\n    @Override\n    public void setReturnSchema(final TypeSchema returnSchema) {\n        this.returnSchema = returnSchema;\n    }\n\n    @Override\n    public List<ParameterDefinition> getParamsList() {\n        return paramsList;\n    }\n\n    /** @param paramsList */\n    public void setParamsList(final List<ParameterDefinition> paramsList) {\n        this.paramsList = paramsList;\n    }\n\n    @Override\n    public TypeSchema getReturnSchema() {\n        return returnSchema;\n    }\n\n    @Override\n    public void setParameterDefinitions(final List<ParameterDefinition> list) {\n        this.paramsList = list;\n    }\n\n    @Override\n    public boolean isUnknownTx() {\n        return isUnknownTx;\n    }\n\n    @Override\n    public void setUnknownTx(final boolean unknown) {\n        this.isUnknownTx = unknown;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/impl/TypeRegistryImpl.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing.impl;\n\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.Map;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\nimport org.hyperledger.fabric.contract.routing.DataTypeDefinition;\nimport org.hyperledger.fabric.contract.routing.TypeRegistry;\n\n/** Registry to hold the complex data types as defined in the contract. */\npublic final class TypeRegistryImpl implements TypeRegistry {\n    private static final TypeRegistryImpl INSTANCE = new TypeRegistryImpl();\n\n    private final Map<String, DataTypeDefinition> components = new HashMap<>();\n\n    /**\n     * Get the TypeRegistry singleton instance.\n     *\n     * @return TypeRegistry\n     */\n    public static TypeRegistry getInstance() {\n        return INSTANCE;\n    }\n\n    /*\n     * (non-Javadoc)\n     *\n     * @see\n     * org.hyperledger.fabric.contract.routing.TypeRegistry#addDataType(java.lang.\n     * Class)\n     */\n    @Override\n    public void addDataType(final Class<?> cl) {\n        final DataTypeDefinitionImpl type = new DataTypeDefinitionImpl(cl);\n        components.put(type.getSimpleName(), type);\n    }\n\n    /*\n     * (non-Javadoc)\n     *\n     * @see org.hyperledger.fabric.contract.routing.TypeRegistry#getAllDataTypes()\n     */\n    @Override\n    public Collection<DataTypeDefinition> getAllDataTypes() {\n        return components.values();\n    }\n\n    @Override\n    public void addDataType(final DataTypeDefinition type) {\n        components.put(type.getName(), type);\n    }\n\n    @Override\n    public DataTypeDefinition getDataType(final String name) {\n        return this.components.get(name);\n    }\n\n    @Override\n    public DataTypeDefinition getDataType(final TypeSchema schema) {\n        final String ref = schema.getRef();\n        final String format = ref.substring(ref.lastIndexOf('/') + 1);\n        return getDataType(format);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/impl/package-info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/** */\npackage org.hyperledger.fabric.contract.routing.impl;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/routing/package-info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/** */\npackage org.hyperledger.fabric.contract.routing;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/systemcontract/SystemContract.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.systemcontract;\n\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.Info;\nimport org.hyperledger.fabric.contract.annotation.Transaction;\nimport org.hyperledger.fabric.contract.metadata.MetadataBuilder;\n\n/** */\n@Contract(\n        name = \"org.hyperledger.fabric\",\n        info =\n                @Info(\n                        title = \"Fabric System Contract\",\n                        description = \"Provides information about the contracts within this container\"))\npublic final class SystemContract implements ContractInterface {\n\n    /**\n     * @param ctx\n     * @return Metadata\n     */\n    @Transaction(intent = Transaction.TYPE.EVALUATE, name = \"GetMetadata\")\n    public String getMetadata(final Context ctx) {\n        return MetadataBuilder.getMetadata();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/systemcontract/package-info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/** */\npackage org.hyperledger.fabric.contract.systemcontract;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/ledger/Collection.java",
    "content": "/*\n * Copyright 2020 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.ledger;\n\n/** Place holder. */\n@SuppressWarnings(\"PMD.ImplicitFunctionalInterface\")\npublic interface Collection {\n\n    /** Constant that can be used to refer to the 'Worldstate' collection explicitly. */\n    String WORLD = \"worldstate\";\n\n    /**\n     * Placeholder. Purely in place to prevent Checkstyle inferring this class is pointless. will be removed in the next\n     * story\n     */\n    void placeholder();\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/ledger/Ledger.java",
    "content": "/*\n * Copyright 2020 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.ledger;\n\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.ledger.impl.LedgerImpl;\n\n/**\n * Ledger representing the overall shared Transaction Data of the Network.\n *\n * <p>It is composed of a number of collections, one being the public or world state, and other private data\n * collections, including the implicit organizational collections.\n *\n * <p>Ledger objects can be passed between methods if required. All operations on the Ledger directly or via any child\n * object such as a Collection will be controlled by the supplied transactional context.\n */\npublic interface Ledger {\n\n    /**\n     * Get the Ledger instance that represents the current ledger state.\n     *\n     * <p>Any interactions with the ledger will be done under the control of the transactional context supplied. The\n     * ledger object may be passed to other methods if required.\n     *\n     * <p>A new instance is returned on each call.\n     *\n     * @param ctx Context The Transactional context to use for interactions with this ledger\n     * @return Ledger instance\n     */\n    static Ledger getLedger(final Context ctx) {\n        return new LedgerImpl(ctx);\n    }\n\n    /**\n     * Return the a collection based on the supplied name.\n     *\n     * <p>Private Data collections can be accessed by name.\n     *\n     * <p>A new instance of a Collection object is returned on each call.\n     *\n     * @param name\n     * @return Collection instance\n     */\n    Collection getCollection(String name);\n\n    /**\n     * Return the World State collection.\n     *\n     * <p>A new instance of a Collection object is returned on each call.\n     *\n     * @return Collection instance\n     */\n    Collection getDefaultCollection();\n\n    /**\n     * Return a implicit organization collection.\n     *\n     * <p>Given the mspid of the ogranization return the private data collection that is implicitly created\n     *\n     * <p>A new instance of a Collection object is returned on each call.\n     *\n     * @param mspid String Organization's mspid\n     * @return Collection instance\n     */\n    Collection getOrganizationCollection(String mspid);\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/ledger/impl/LedgerImpl.java",
    "content": "/*\n * Copyright 2020 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.ledger.impl;\n\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.ledger.Collection;\nimport org.hyperledger.fabric.ledger.Ledger;\n\npublic final class LedgerImpl implements Ledger {\n\n    /**\n     * New Ledger Implementation.\n     *\n     * @param ctx Context transactional context to use\n     */\n    public LedgerImpl(final Context ctx) {\n        // Empty stub\n    }\n\n    @Override\n    public Collection getCollection(final String name) {\n        return new Collection() {\n            @Override\n            public void placeholder() {\n                // Empty stub\n            }\n        };\n    }\n\n    @Override\n    public Collection getDefaultCollection() {\n        return this.getCollection(Collection.WORLD);\n    }\n\n    @Override\n    public Collection getOrganizationCollection(final String mspid) {\n        return this.getCollection(\"_implicit_org_\" + mspid);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/ledger/impl/package-info.java",
    "content": "/*\n * Copyright 2023 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.ledger.impl;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/ledger/package-info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/** Provides the API for contracts to access the shared ledger. */\npackage org.hyperledger.fabric.ledger;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/metrics/Metrics.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.metrics;\n\nimport java.util.Properties;\nimport java.util.logging.Logger;\nimport org.hyperledger.fabric.metrics.impl.DefaultProvider;\nimport org.hyperledger.fabric.metrics.impl.NullProvider;\n\n/**\n * Metrics Interface.\n *\n * <p>Metrics setups up the provider in use from the configuration supplied If not enabled, nothing happens, but if\n * enabled but no specific logger default is used that uses the org.hyperledger.Performance logger\n */\npublic final class Metrics {\n\n    private static final String CHAINCODE_METRICS_ENABLED = \"CHAINCODE_METRICS_ENABLED\";\n    private static final String CHAINCODE_METRICS_PROVIDER = \"CHAINCODE_METRICS_PROVIDER\";\n\n    private static Logger logger = Logger.getLogger(Metrics.class.getName());\n\n    private static MetricsProvider provider;\n\n    private Metrics() {}\n\n    /**\n     * @param props\n     * @return The metrics provide\n     */\n    @SuppressWarnings(\"PMD.AvoidCatchingGenericException\")\n    public static MetricsProvider initialize(final Properties props) {\n        if (Boolean.parseBoolean((String) props.get(CHAINCODE_METRICS_ENABLED))) {\n            try {\n                logger.info(\"Metrics enabled\");\n                if (props.containsKey(CHAINCODE_METRICS_PROVIDER)) {\n                    final String providerClass = (String) props.get(CHAINCODE_METRICS_PROVIDER);\n\n                    @SuppressWarnings(\"unchecked\") // it must be this type otherwise an error\n                    final Class<MetricsProvider> clazz = (Class<MetricsProvider>) Class.forName(providerClass);\n                    provider = clazz.getConstructor().newInstance();\n                } else {\n                    logger.info(\"Using default metrics provider (logs to org.hyperledger.Performance)\");\n                    provider = new DefaultProvider();\n                }\n            } catch (Exception e) {\n                throw new IllegalStateException(\"Unable to start metrics\", e);\n            }\n        } else {\n            // return a 'null' provider\n            logger.info(\"Metrics disabled\");\n            provider = new NullProvider();\n        }\n\n        provider.initialize(props);\n        return provider;\n    }\n\n    /** @return MetricsProvider */\n    public static MetricsProvider getProvider() {\n        if (provider == null) {\n            throw new IllegalStateException(\"No provider set, this should have been set\");\n        }\n        return provider;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/metrics/MetricsProvider.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.metrics;\n\nimport java.util.Properties;\n\n/**\n * Interface to be implemented to send metrics on the chaincode to the 'backend-of-choice'.\n *\n * <p>An instance of this will be created, and provided with the resources from which chaincode specific metrics can be\n * collected. (via the no-argument constructor).\n *\n * <p>The choice of when, where and what to collect etc are within the remit of the provider.\n *\n * <p>This is the effective call sequence.\n *\n * <p>MyMetricsProvider mmp = new MyMetricsProvider() mmp.initialize(props_from_environment); // short while later....\n * mmp.setTaskMetricsCollector(taskService);\n */\npublic interface MetricsProvider {\n\n    /**\n     * Initialize method that is called immediately after creation.\n     *\n     * @param props\n     */\n    default void initialize(final Properties props) {\n        // Do nothing by default\n    }\n\n    /**\n     * Pass a reference to this task service for information gathering. This is related specifically to the handling of\n     * tasks within the chaincode. i.e. how individual transactions are dispatched for execution.\n     *\n     * @param taskService\n     */\n    default void setTaskMetricsCollector(final TaskMetricsCollector taskService) {\n        // Do nothing by default\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/metrics/TaskMetricsCollector.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.metrics;\n\n/**\n * Collect metrics relating to the task execution.\n *\n * <p>The task execution (of which each fabric transaction is one) is backed by a thread pool that implements this\n * interface. As that is an implementation class this interface abstracts the information available from it (as far as\n * metrics go).\n */\npublic interface TaskMetricsCollector {\n\n    /**\n     * Currently executing tasks.\n     *\n     * @return int &gt; 0\n     */\n    int getCurrentTaskCount();\n\n    /**\n     * Currently waiting tasks; should not be a higher number.\n     *\n     * @return int &gt; 0\n     */\n    int getCurrentQueueCount();\n\n    /**\n     * Currently executing threads.\n     *\n     * @return int &gt; 0\n     */\n    int getActiveCount();\n\n    /**\n     * Gets the current size of the pool.\n     *\n     * @return int &gt; 0\n     */\n    int getPoolSize();\n\n    /**\n     * Gets the core (minimum) pool size.\n     *\n     * @return int &gt; 0\n     */\n    int getCorePoolSize();\n\n    /**\n     * Gets the largest pool size so far.\n     *\n     * @return int &gt; 0\n     */\n    int getLargestPoolSize();\n\n    /**\n     * Gets the upper limit pool size.\n     *\n     * @return int &gt; 0\n     */\n    int getMaximumPoolSize();\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/metrics/impl/DefaultProvider.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.metrics.impl;\n\nimport java.util.Properties;\nimport java.util.Timer;\nimport java.util.TimerTask;\nimport java.util.logging.Logger;\nimport org.hyperledger.fabric.Logging;\nimport org.hyperledger.fabric.metrics.MetricsProvider;\nimport org.hyperledger.fabric.metrics.TaskMetricsCollector;\n\n/** Simple default provider that logs to the org.hyperledger.Performance logger the basic metrics. */\npublic final class DefaultProvider implements MetricsProvider {\n    private static final Logger PERFLOGGER = Logger.getLogger(Logging.PERFLOGGER);\n    private static final int TIME_INTERVAL = 5000;\n\n    private TaskMetricsCollector taskService;\n\n    /** */\n    public DefaultProvider() {\n        PERFLOGGER.info(\"Default Metrics Provider started\");\n    }\n\n    @Override\n    public void setTaskMetricsCollector(final TaskMetricsCollector taskService) {\n        this.taskService = taskService;\n    }\n\n    @Override\n    public void initialize(final Properties props) {\n        final Timer metricTimer = new Timer(true);\n        metricTimer.scheduleAtFixedRate(\n                new TimerTask() {\n                    @Override\n                    public void run() {\n                        DefaultProvider.this.logMetrics();\n                    }\n                },\n                0,\n                TIME_INTERVAL);\n    }\n\n    void logMetrics() {\n        PERFLOGGER.info(() -> {\n            if (taskService == null) {\n                return \"No Metrics Provider service yet\";\n            }\n            return '{'\n                    + String.format(\" \\\"active_count\\\":%d \", taskService.getActiveCount())\n                    + ','\n                    + String.format(\" \\\"pool_size\\\":%d \", taskService.getPoolSize())\n                    + ','\n                    + String.format(\" \\\"core_pool_size\\\":%d \", taskService.getCorePoolSize())\n                    + ','\n                    + String.format(\" \\\"current_task_count\\\":%d \", taskService.getCurrentTaskCount())\n                    + ','\n                    + String.format(\" \\\"current_queue_depth\\\":%d \", taskService.getCurrentQueueCount())\n                    + '}';\n        });\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/metrics/impl/NullProvider.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.metrics.impl;\n\nimport org.hyperledger.fabric.metrics.MetricsProvider;\n\n/** Very simple provider that does absolutely nothing. Used when metrics are disabled. */\npublic class NullProvider implements MetricsProvider {}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/metrics/impl/package-info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/** */\npackage org.hyperledger.fabric.metrics.impl;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/metrics/package-info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Provides interfaces and classes to support collection of metrics.\n *\n * <p>The main metrics that are available are the statistics around the number of tasks that are running, and how the\n * thread pool is handling these.\n *\n * <p>Note a 'task' is a message from the Peer to the Chaincode - this message is either a new transaction, or a\n * response from a stub API, eg getState(). Query apis may return more than one response.\n *\n * <p>To enable metrics, add a <code>CHAINCODE_METRICS_ENABLED=true</code> setting to the <code>config.props</code>\n * chaincode configuration file. See the <a href=\"../../../../index.html\">Overview</a> for details of how to configure\n * chaincode.\n *\n * <p>Open Telemetry To use Open Telemetry, set the following properties:\n *\n * <pre>\n * CHAINCODE_METRICS_ENABLED=true\n * CHAINCODE_METRICS_PROVIDER=org.hyperledger.fabric.metrics.impl.OpenTelemetryMetricsProvider\n * </pre>\n *\n * Additionally, you can set properties after the specification:\n * https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/sdk-environment-variables.md\n *\n * <p>Example:\n *\n * <pre>\n * OTEL_EXPORTER_OTLP_ENDPOINT=otelcollector:4317\n * OTEL_EXPORTER_OTLP_INSECURE=true\n * </pre>\n */\npackage org.hyperledger.fabric.metrics;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/overview.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n<!-- SPDX-License-Identifier: Apache-2.0 -->\n<html>\n  <body>\n    <p>This is the project to support the writing of Contracts with the JVM runtime - enabling development of using Java language or other JVM based languages</p>\n\n    <p>The Fabric programming model is described in the <a href=\"https://hyperledger-fabric.readthedocs.io/en/latest/developapps/developing_applications.html\">Developing Applications</a> chapter of the Hyperledger Fabric documentation.</p>\n\n    <p>All Contracts should implement {@link org.hyperledger.fabric.contract.ContractInterface} interface, in addition to the {@link org.hyperledger.fabric.contract.annotation.Contract} annotation.</p>\n\n    <h2>Configuration</h2>\n\n    <p>\n      Some Java chaincode settings are configurable on a per chaincode basis, including the maximum gRPC inbound message size, thread pool settings, and whether to enable chaincode metrics.\n      The default settings are as follows:\n    </p>\n\n    <pre>\n      MAX_INBOUND_MESSAGE_SIZE=104857600\n      CHAINCODE_METRICS_ENABLED=false\n      TP_CORE_POOL_SIZE=5\n      TP_MAX_POOL_SIZE=5\n      TP_QUEUE_SIZE=5000\n    </pre>\n\n    <p>\n      To override the defaults, a <code>config.props</code> Java properties file must be included in the default, unnamed, package on your contract code's classpath, which will then be loaded when the chaincode starts.\n      Setting the metrics enabled flag to <code>true</code> will turn on default metrics logging. The <code>TP_</code> values establish the core thread pool size, max thread poolsize, and the number of of tasks that will wait.\n    </p>\n\n\n    <h3>Open Telemetry</h3>\n    <p>\n    To use Open Telemetry, set the following properties:\n    </p>\n    <pre>\n      CHAINCODE_METRICS_ENABLED=true\n      CHAINCODE_METRICS_PROVIDER=org.hyperledger.fabric.metrics.impl.OpenTelemetryMetricsProvider\n    </pre>\n    <p>\n    Additionally, you can set properties after the <a href=\"https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/sdk-environment-variables.md\">OpenTelemetry specification</a>.<br>\n    Example:\n    </p>\n    <pre>\n      OTEL_EXPORTER_OTLP_ENDPOINT=otelcollector:4317\n      OTEL_EXPORTER_OTLP_INSECURE=true\n    </pre>\n\n\n    <p>\n      If you are building your chaincode using Gradle or Maven, create a <code>config.props</code> file in the <code>src/main/resources</code> directory and include the settings you want to override.\n    </p>\n  </body>\n</html>\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/package-info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/** Provides logging classes. */\npackage org.hyperledger.fabric;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/Chaincode.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim;\n\nimport static java.nio.charset.StandardCharsets.UTF_8;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/** Defines methods that all chaincodes must implement. */\npublic interface Chaincode {\n    /**\n     * Called during an instantiate transaction after the container has been established, allowing the chaincode to\n     * initialize its internal data.\n     *\n     * @param stub the chaincode stub\n     * @return the chaincode response\n     */\n    Response init(ChaincodeStub stub);\n\n    /**\n     * Called for every Invoke transaction. The chaincode may change its state variables.\n     *\n     * @param stub the chaincode stub\n     * @return the chaincode response\n     */\n    Response invoke(ChaincodeStub stub);\n\n    /**\n     * Wrapper around protobuf Response, contains status, message and payload. Object returned by call to\n     * {@link #init(ChaincodeStub)} and{@link #invoke(ChaincodeStub)}\n     */\n    class Response {\n        private final int statusCode;\n        private final String message;\n        private final byte[] payload;\n\n        /**\n         * Constructor.\n         *\n         * @param status a status object.\n         * @param message a response message.\n         * @param payload a response payload.\n         */\n        @SuppressWarnings(\"PMD.ArrayIsStoredDirectly\")\n        public Response(final Status status, final String message, final byte[] payload) {\n            this.statusCode = status.getCode();\n            this.message = message;\n            this.payload = payload;\n        }\n\n        /**\n         * Constructor.\n         *\n         * @param statusCode a status code.\n         * @param message a response message.\n         * @param payload a response payload.\n         */\n        @SuppressWarnings(\"PMD.ArrayIsStoredDirectly\")\n        public Response(final int statusCode, final String message, final byte[] payload) {\n            this.statusCode = statusCode;\n            this.message = message;\n            this.payload = payload;\n        }\n\n        /**\n         * Get the response status.\n         *\n         * @return status.\n         */\n        public Status getStatus() {\n            if (Status.hasStatusForCode(statusCode)) {\n                return Status.forCode(statusCode);\n            } else {\n                return null;\n            }\n        }\n\n        /**\n         * Get the response status code.\n         *\n         * @return status code.\n         */\n        public int getStatusCode() {\n            return statusCode;\n        }\n\n        /**\n         * Get the response message.\n         *\n         * @return a message.\n         */\n        public String getMessage() {\n            return message;\n        }\n\n        /**\n         * Get the response payload.\n         *\n         * @return payload bytes.\n         */\n        @SuppressWarnings(\"PMD.MethodReturnsInternalArray\")\n        public byte[] getPayload() {\n            return payload;\n        }\n\n        /**\n         * Get the response payload as a UTF-8 string.\n         *\n         * @return a string.\n         */\n        public String getStringPayload() {\n            return (payload == null) ? null : new String(payload, UTF_8);\n        }\n\n        /** {@link Response} status enum. */\n        public enum Status {\n            /** Successful response status. */\n            SUCCESS(200),\n            /** Minimum threshold for as error status code. */\n            ERROR_THRESHOLD(400),\n            /** Server-side error status. */\n            INTERNAL_SERVER_ERROR(500);\n\n            private static final Map<Integer, Status> CODETOSTATUS = new HashMap<>();\n            private final int code;\n\n            Status(final int code) {\n                this.code = code;\n            }\n\n            /**\n             * Get the status code associated with this status object.\n             *\n             * @return a status code.\n             */\n            public int getCode() {\n                return code;\n            }\n\n            /**\n             * Get a status object for a given status code.\n             *\n             * @param code a status code.\n             * @return a status object.\n             */\n            public static Status forCode(final int code) {\n                final Status result = CODETOSTATUS.get(code);\n                if (result == null) {\n                    throw new IllegalArgumentException(\"no status for code \" + code);\n                }\n                return result;\n            }\n\n            /**\n             * Whether a status exists for a given status code.\n             *\n             * @param code a status code.\n             * @return True if a status for the code exists; otherwise false.\n             */\n            public static boolean hasStatusForCode(final int code) {\n                return CODETOSTATUS.containsKey(code);\n            }\n\n            static {\n                for (final Status status : values()) {\n                    CODETOSTATUS.put(status.code, status);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ChaincodeBase.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim;\n\nimport static java.util.logging.Level.ALL;\n\nimport com.google.protobuf.InvalidProtocolBufferException;\nimport com.google.protobuf.util.JsonFormat;\nimport io.grpc.ManagedChannelBuilder;\nimport io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts;\nimport io.grpc.netty.shaded.io.grpc.netty.NegotiationType;\nimport io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder;\nimport io.grpc.netty.shaded.io.netty.handler.ssl.SslContext;\nimport io.grpc.stub.StreamObserver;\nimport java.io.ByteArrayInputStream;\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.InetSocketAddress;\nimport java.net.SocketAddress;\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.security.Security;\nimport java.util.Base64;\nimport java.util.Locale;\nimport java.util.Properties;\nimport java.util.logging.Level;\nimport java.util.logging.LogRecord;\nimport java.util.logging.Logger;\nimport java.util.logging.SimpleFormatter;\nimport org.apache.commons.cli.CommandLine;\nimport org.apache.commons.cli.DefaultParser;\nimport org.apache.commons.cli.Options;\nimport org.bouncycastle.jce.provider.BouncyCastleProvider;\nimport org.hyperledger.fabric.Logging;\nimport org.hyperledger.fabric.contract.ContractRouter;\nimport org.hyperledger.fabric.metrics.Metrics;\nimport org.hyperledger.fabric.protos.peer.ChaincodeID;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.shim.impl.ChaincodeSupportClient;\nimport org.hyperledger.fabric.shim.impl.InvocationTaskManager;\nimport org.hyperledger.fabric.traces.Traces;\n\n/**\n * Abstract implementation of {@link Chaincode}.\n *\n * <p>All chaincode implementations must extend the abstract class <code>ChaincodeBase</code>. It is possible to\n * implement chaincode by extending <code>ChaincodeBase</code> directly however new projects should implement\n * {@link org.hyperledger.fabric.contract.ContractInterface} and use the contract programming model instead.\n *\n * @see org.hyperledger.fabric.contract\n */\n@SuppressWarnings({\"PMD.CyclomaticComplexity\", \"PMD.GodClass\"})\npublic abstract class ChaincodeBase implements Chaincode {\n\n    /** */\n    public static final String CORE_CHAINCODE_LOGGING_SHIM = \"CORE_CHAINCODE_LOGGING_SHIM\";\n\n    /** */\n    public static final String CORE_CHAINCODE_LOGGING_LEVEL = \"CORE_CHAINCODE_LOGGING_LEVEL\";\n\n    private static final Logger LOGGER = Logger.getLogger(ChaincodeBase.class.getName());\n\n    /** */\n    @SuppressWarnings(\"PMD.AvoidUsingHardCodedIP\")\n    public static final String DEFAULT_HOST = \"127.0.0.1\";\n\n    /** */\n    public static final int DEFAULT_PORT = 7051;\n\n    /** Default to 100MB for maximum inbound grpc message size. */\n    public static final String DEFAULT_MAX_INBOUND_MESSAGE_SIZE = \"104857600\";\n\n    private String host = DEFAULT_HOST;\n    private int port = DEFAULT_PORT;\n    private boolean tlsEnabled;\n    private String tlsClientKeyPath;\n    private String tlsClientCertPath;\n    private String tlsClientKeyFile;\n    private String tlsClientCertFile;\n    private String tlsClientRootCertPath;\n\n    private String id;\n    private String localMspId = \"\";\n    private String chaincodeServerAddress = \"\";\n\n    private static final String CHAINCODE_SERVER_ADDRESS = \"CHAINCODE_SERVER_ADDRESS\";\n    private static final String CORE_CHAINCODE_ID_NAME = \"CORE_CHAINCODE_ID_NAME\";\n    private static final String CORE_PEER_ADDRESS = \"CORE_PEER_ADDRESS\";\n    private static final String CORE_PEER_TLS_ENABLED = \"CORE_PEER_TLS_ENABLED\";\n    private static final String CORE_PEER_TLS_ROOTCERT_FILE = \"CORE_PEER_TLS_ROOTCERT_FILE\";\n    private static final String ENV_TLS_CLIENT_KEY_PATH = \"CORE_TLS_CLIENT_KEY_PATH\";\n    private static final String ENV_TLS_CLIENT_CERT_PATH = \"CORE_TLS_CLIENT_CERT_PATH\";\n    private static final String ENV_TLS_CLIENT_KEY_FILE = \"CORE_TLS_CLIENT_KEY_FILE\";\n    private static final String ENV_TLS_CLIENT_CERT_FILE = \"CORE_TLS_CLIENT_CERT_FILE\";\n    private static final String CORE_PEER_LOCALMSPID = \"CORE_PEER_LOCALMSPID\";\n    private static final String MAX_INBOUND_MESSAGE_SIZE = \"MAX_INBOUND_MESSAGE_SIZE\";\n    private Properties props;\n    private Level logLevel;\n    private CCState state = CCState.CREATED;\n\n    static {\n        Security.addProvider(new BouncyCastleProvider());\n    }\n\n    @Override\n    public abstract Response init(ChaincodeStub stub);\n\n    @Override\n    public abstract Response invoke(ChaincodeStub stub);\n\n    private int getMaxInboundMessageSize() {\n        if (this.props == null) {\n            throw new IllegalStateException(\"Chaincode config not available\");\n        }\n        final int maxMsgSize =\n                Integer.parseInt(this.props.getProperty(MAX_INBOUND_MESSAGE_SIZE, DEFAULT_MAX_INBOUND_MESSAGE_SIZE));\n        final String msgSizeInfo =\n                String.format(\"Maximum Inbound Message Size [%s] = %d\", MAX_INBOUND_MESSAGE_SIZE, maxMsgSize);\n        LOGGER.info(msgSizeInfo);\n        return maxMsgSize;\n    }\n\n    /**\n     * Start chaincode.\n     *\n     * @param args command line arguments\n     */\n    @SuppressWarnings(\"PMD.AvoidCatchingGenericException\")\n    public void start(final String[] args) {\n        try {\n            initializeLogging();\n            processEnvironmentOptions();\n            processCommandLineOptions(args);\n            validateOptions();\n\n            final Properties props = getChaincodeConfig();\n            Metrics.initialize(props);\n            Traces.initialize(props);\n            connectToPeer();\n        } catch (final Exception e) {\n            LOGGER.severe(() -> \"Chaincode could not start\" + Logging.formatError(e));\n        }\n    }\n\n    protected final void connectToPeer() throws IOException {\n\n        // The ChaincodeSupport Client is a wrapper around the gRPC streams that\n        // come from the single 'register' call that is made back to the peer\n        //\n        // Once this has been created, the InvocationTaskManager that is responsible\n        // for the thread management can be created.\n        //\n        // This is then passed to the ChaincodeSupportClient to be connected to the\n        // gRPC streams\n\n        final ChaincodeID chaincodeId =\n                ChaincodeID.newBuilder().setName(this.id).build();\n        final ManagedChannelBuilder<?> channelBuilder = newChannelBuilder();\n        final ChaincodeSupportClient chaincodeSupportClient = new ChaincodeSupportClient(channelBuilder);\n\n        final InvocationTaskManager itm = InvocationTaskManager.getManager(this, chaincodeId);\n\n        // This is a critical method - it is the one time that a\n        // protobuf service is invoked. The single 'register' call\n        // is made, and two streams are created.\n        //\n        // It is confusing how these streams are then used to send messages\n        // to and from the peer.\n        //\n        // the response stream is the message flow FROM the peer\n        // the 'request observer' is the message flow TO the peer\n        //\n        // Messages coming from the peer will be requests to invoke\n        // chaincode, or will be the responses to stub APIs, such as getState\n        // Message to the peer will be the getState APIs, and the results of\n        // transaction invocations\n\n        // The InnvocationTaskManager's way of being told there is a new\n        // message, until this is received and processed there is now\n        // knowing if this is a new transaction function or the answer to say getState\n\n        LOGGER.info(\"making the grpc call\");\n        // for any error - shut everything down\n        // as this is long lived (well forever) then any completion means something\n        // has stopped in the peer or the network comms, so also shutdown\n        final StreamObserver<ChaincodeMessage> requestObserver = chaincodeSupportClient\n                .getStub()\n                .register(new StreamObserver<>() {\n                    @Override\n                    public void onNext(final ChaincodeMessage chaincodeMessage) {\n                        // message off to the ITM...\n                        itm.onChaincodeMessage(chaincodeMessage);\n                    }\n\n                    @Override\n                    public void onError(final Throwable t) {\n                        LOGGER.severe(\n                                () -> \"An error occurred on the chaincode stream. Shutting down the chaincode stream.\"\n                                        + Logging.formatError(t));\n\n                        chaincodeSupportClient.shutdown(itm);\n                    }\n\n                    @Override\n                    public void onCompleted() {\n                        LOGGER.severe(\"Chaincode stream is complete. Shutting down the chaincode stream.\");\n                        chaincodeSupportClient.shutdown(itm);\n                    }\n                });\n\n        chaincodeSupportClient.start(itm, requestObserver);\n    }\n\n    /**\n     * connect external chaincode to peer for chat.\n     *\n     * @param requestObserver reqeust from peer\n     * @return itm - The InnvocationTask Manager handles the message level communication with the peer.\n     * @throws IOException validation fields exception\n     */\n    protected StreamObserver<ChaincodeMessage> connectToPeer(final StreamObserver<ChaincodeMessage> requestObserver)\n            throws IOException {\n        validateOptions();\n        if (requestObserver == null) {\n            throw new IOException(\"StreamObserver 'requestObserver' for chat with peer can't be null\");\n        }\n        // The ChaincodeSupport Client is a wrapper around the gRPC streams that\n        // come from the single 'register' call that is made back to the peer\n        //\n        // Once this has been created, the InnvocationTaskManager that is responsible\n        // for the thread management can be created.\n        //\n        // This is then passed to the ChaincodeSupportClient to be connected to the\n        // gRPC streams\n\n        final ChaincodeID chaincodeId =\n                ChaincodeID.newBuilder().setName(this.id).build();\n        final ManagedChannelBuilder<?> channelBuilder = newChannelBuilder();\n        final ChaincodeSupportClient chaincodeSupportClient = new ChaincodeSupportClient(channelBuilder);\n\n        final InvocationTaskManager itm = InvocationTaskManager.getManager(this, chaincodeId);\n\n        chaincodeSupportClient.start(itm, requestObserver);\n\n        return new StreamObserver<>() {\n            @Override\n            public void onNext(final ChaincodeMessage chaincodeMessage) {\n                itm.onChaincodeMessage(chaincodeMessage);\n            }\n\n            @Override\n            public void onError(final Throwable t) {\n                LOGGER.severe(() -> \"An error occurred on the chaincode stream. Shutting down the chaincode stream.\"\n                        + Logging.formatError(t));\n\n                chaincodeSupportClient.shutdown(itm);\n            }\n\n            @Override\n            public void onCompleted() {\n                LOGGER.severe(\"Chaincode stream is complete. Shutting down the chaincode stream.\");\n                chaincodeSupportClient.shutdown(itm);\n            }\n        };\n    }\n\n    protected final void initializeLogging() {\n        // the VM wide formatting string.\n        System.setProperty(\n                \"java.util.logging.SimpleFormatter.format\", \"%1$tH:%1$tM:%1$tS:%1$tL %4$-7.7s %2$-80.80s %5$s%6$s%n\");\n        final Logger rootLogger = Logger.getLogger(\"\");\n\n        var formatter = new SimpleFormatter() {\n            @Override\n            public String format(final LogRecord record) {\n                return Thread.currentThread() + \" \" + super.format(record);\n            }\n        };\n\n        for (final java.util.logging.Handler handler : rootLogger.getHandlers()) {\n            handler.setLevel(ALL);\n            handler.setFormatter(formatter);\n        }\n\n        rootLogger.info(\"Updated all handlers the format\");\n        // set logging level of chaincode logger\n        final Level chaincodeLogLevel = mapLevel(System.getenv(CORE_CHAINCODE_LOGGING_LEVEL));\n\n        final Package chaincodePackage = this.getClass().getPackage();\n        if (chaincodePackage != null) {\n            Logger.getLogger(chaincodePackage.getName()).setLevel(chaincodeLogLevel);\n        } else {\n            // If chaincode declared without package, i.e. default package, lets set level\n            // to root logger\n            // Chaincode should never be declared without package\n            Logger.getLogger(\"\").setLevel(chaincodeLogLevel);\n        }\n\n        // set logging level of shim logger\n        final Level shimLogLevel = mapLevel(System.getenv(CORE_CHAINCODE_LOGGING_SHIM));\n        Logger.getLogger(ChaincodeBase.class.getPackage().getName()).setLevel(shimLogLevel);\n        Logger.getLogger(ContractRouter.class.getPackage().getName()).setLevel(chaincodeLogLevel);\n    }\n\n    private Level mapLevel(final String level) {\n\n        if (level != null) {\n            switch (level.toUpperCase(Locale.getDefault()).trim()) {\n                case \"CRITICAL\":\n                case \"ERROR\":\n                    return Level.SEVERE;\n                case \"WARNING\":\n                case \"WARN\":\n                    return Level.WARNING;\n                case \"INFO\":\n                    return Level.INFO;\n                case \"NOTICE\":\n                    return Level.CONFIG;\n                case \"DEBUG\":\n                    return Level.FINEST;\n                default:\n                    break;\n            }\n        }\n        return Level.INFO;\n    }\n\n    private SocketAddress parseHostPort(final String hostAddrStr) throws URISyntaxException {\n\n        // WORKAROUND: add any scheme to make the resulting URI valid.\n        URI uri = new URI(\"my://\" + hostAddrStr); // may throw URISyntaxException\n        String host = uri.getHost();\n        int port = uri.getPort();\n\n        if (host == null || port == -1) {\n            throw new URISyntaxException(uri.toString(), \"URI must have host and port parts\");\n        }\n\n        // validation succeeded\n        return new InetSocketAddress(host, port);\n    }\n\n    /**\n     * Use the CHAINCODE_SERVER_ADDRESS as the key to swap mode.\n     *\n     * @return true if this should be run as `chaincode-as-a-service`\n     */\n    public boolean isServer() {\n        return !chaincodeServerAddress.isEmpty();\n    }\n\n    /** Validate init parameters from env chaincode base. */\n    @SuppressWarnings(\"PMD.CyclomaticComplexity\")\n    public void validateOptions() {\n        if (this.id == null || this.id.isEmpty()) {\n            throw new IllegalArgumentException(String.format(\n                    \"The chaincode id must be specified using either the -i or --i command line options or the %s environment variable.\",\n                    CORE_CHAINCODE_ID_NAME));\n        }\n        if (this.tlsEnabled) {\n            if (tlsClientCertPath == null) {\n                throw new IllegalArgumentException(String.format(\n                        \"Client key certificate chain (%s) was not specified.\", ENV_TLS_CLIENT_CERT_PATH));\n            }\n            if (tlsClientKeyPath == null) {\n                throw new IllegalArgumentException(\n                        String.format(\"Client key (%s) was not specified.\", ENV_TLS_CLIENT_KEY_PATH));\n            }\n            if (tlsClientRootCertPath == null) {\n                throw new IllegalArgumentException(String.format(\n                        \"Peer certificate trust store (%s) was not specified.\", CORE_PEER_TLS_ROOTCERT_FILE));\n            }\n        }\n    }\n\n    @SuppressWarnings({\n        \"PMD.AvoidLiteralsInIfCondition\",\n        \"PMD.AvoidCatchingGenericException\",\n        \"PMD.ExceptionAsFlowControl\"\n    })\n    protected final void processCommandLineOptions(final String[] args) {\n        final Options options = new Options();\n        options.addOption(\"a\", \"peer.address\", true, \"Address of peer to connect to\");\n        options.addOption(null, \"peerAddress\", true, \"Address of peer to connect to\");\n        options.addOption(\"i\", \"id\", true, \"Identity of chaincode\");\n\n        try {\n            final CommandLine cl = new DefaultParser().parse(options, args);\n            if (cl.hasOption(\"peerAddress\") || cl.hasOption('a')) {\n                String hostAddrStr;\n                if (cl.hasOption('a')) {\n                    hostAddrStr = cl.getOptionValue('a');\n                } else {\n                    hostAddrStr = cl.getOptionValue(\"peerAddress\");\n                }\n                final String[] hostArr = hostAddrStr.split(\":\");\n                if (hostArr.length == 2) {\n                    port = Integer.parseInt(hostArr[1].trim());\n                    host = hostArr[0].trim();\n                } else {\n                    final String msg = String.format(\n                            \"peer address argument should be in host:port format, current %s in wrong\", hostAddrStr);\n                    LOGGER.severe(msg);\n                    throw new IllegalArgumentException(msg);\n                }\n            }\n            if (cl.hasOption('i')) {\n                id = cl.getOptionValue('i');\n            }\n        } catch (final Exception e) {\n            LOGGER.warning(() -> \"cli parsing failed with exception\" + Logging.formatError(e));\n        }\n\n        LOGGER.info(() -> \"<<<<<<<<<<<<<CommandLine options>>>>>>>>>>>>\" + \"\\nCORE_CHAINCODE_ID_NAME: \"\n                + this.id + \"\\nCORE_PEER_ADDRESS: \"\n                + this.host + \":\" + this.port);\n    }\n\n    /** set fields from env. */\n    @SuppressWarnings(\"PMD.AvoidLiteralsInIfCondition\")\n    public final void processEnvironmentOptions() {\n\n        if (System.getenv().containsKey(CORE_CHAINCODE_ID_NAME)) {\n            this.id = System.getenv(CORE_CHAINCODE_ID_NAME);\n        }\n        if (System.getenv().containsKey(CORE_PEER_ADDRESS)) {\n            final String[] hostArr = System.getenv(CORE_PEER_ADDRESS).split(\":\");\n            if (hostArr.length == 2) {\n                this.port = Integer.parseInt(hostArr[1].trim());\n                this.host = hostArr[0].trim();\n            } else {\n                final String msg = String.format(\n                        \"peer address argument should be in host:port format, ignoring current %s\",\n                        System.getenv(CORE_PEER_ADDRESS));\n                LOGGER.severe(msg);\n            }\n        }\n\n        if (System.getenv().containsKey(CHAINCODE_SERVER_ADDRESS)) {\n            this.chaincodeServerAddress = System.getenv(CHAINCODE_SERVER_ADDRESS);\n        }\n\n        if (System.getenv().containsKey(CORE_PEER_LOCALMSPID)) {\n            this.localMspId = System.getenv(CORE_PEER_LOCALMSPID);\n        }\n\n        this.tlsEnabled = Boolean.parseBoolean(System.getenv(CORE_PEER_TLS_ENABLED));\n        if (this.tlsEnabled) {\n            this.tlsClientRootCertPath = System.getenv(CORE_PEER_TLS_ROOTCERT_FILE);\n            this.tlsClientKeyPath = System.getenv(ENV_TLS_CLIENT_KEY_PATH);\n            this.tlsClientCertPath = System.getenv(ENV_TLS_CLIENT_CERT_PATH);\n\n            this.tlsClientKeyFile = System.getenv(ENV_TLS_CLIENT_KEY_FILE);\n            this.tlsClientCertFile = System.getenv(ENV_TLS_CLIENT_CERT_FILE);\n        }\n\n        if (LOGGER.isLoggable(Level.INFO)) {\n            LOGGER.info(\"<<<<<<<<<<<<<Environment options>>>>>>>>>>>>\");\n            LOGGER.info(\"CORE_CHAINCODE_ID_NAME: \" + this.id);\n            LOGGER.info(\"CORE_PEER_ADDRESS: \" + this.host);\n            LOGGER.info(\"CORE_PEER_TLS_ENABLED: \" + this.tlsEnabled);\n            LOGGER.info(\"CORE_PEER_TLS_ROOTCERT_FILE: \" + this.tlsClientRootCertPath);\n            LOGGER.info(\"CORE_TLS_CLIENT_KEY_PATH: \" + this.tlsClientKeyPath);\n            LOGGER.info(\"CORE_TLS_CLIENT_CERT_PATH: \" + this.tlsClientCertPath);\n            LOGGER.info(\"CORE_TLS_CLIENT_KEY_FILE: \" + this.tlsClientKeyFile);\n            LOGGER.info(\"CORE_TLS_CLIENT_CERT_FILE: \" + this.tlsClientCertFile);\n            LOGGER.info(\"CORE_PEER_LOCALMSPID: \" + this.localMspId);\n            LOGGER.info(\"CHAINCODE_SERVER_ADDRESS: \" + this.chaincodeServerAddress);\n            LOGGER.info(\"LOGLEVEL: \" + this.logLevel);\n        }\n    }\n\n    /**\n     * Obtains configuration specifically for running the chaincode and settable on a per chaincode basis rather than\n     * taking properties from the Peers' configuration.\n     *\n     * @return Configuration\n     */\n    public Properties getChaincodeConfig() {\n        if (this.props == null) {\n\n            final ClassLoader cl = this.getClass().getClassLoader();\n            // determine the location of the properties file to control the metrics etc.\n\n            props = new Properties();\n\n            try (InputStream inStream = cl.getResourceAsStream(\"config.props\")) {\n                if (inStream != null) {\n                    props.load(inStream);\n                }\n            } catch (final IOException e) {\n                LOGGER.warning(() -> \"Can not open the properties file for input \" + Logging.formatError(e));\n            }\n\n            // will be useful\n            props.setProperty(CORE_CHAINCODE_ID_NAME, this.id);\n            props.setProperty(CORE_PEER_ADDRESS, this.host);\n\n            LOGGER.info(\"<<<<<<<<<<<<<Properties options>>>>>>>>>>>>\");\n            LOGGER.info(this.props::toString);\n        }\n\n        return this.props;\n    }\n\n    /**\n     * The properties for starting as chaincode-as-a-service.\n     *\n     * @return ChaincodeServerProperties populated\n     */\n    public final ChaincodeServerProperties getChaincodeServerConfig() throws URISyntaxException {\n        ChaincodeServerProperties chaincodeServerProperties = new ChaincodeServerProperties();\n\n        chaincodeServerProperties.setServerAddress(parseHostPort(chaincodeServerAddress));\n\n        if (tlsEnabled) {\n\n            // set values on the server properties\n            chaincodeServerProperties.setTlsEnabled(true);\n            chaincodeServerProperties.setKeyFile(this.tlsClientKeyFile);\n            chaincodeServerProperties.setKeyCertChainFile(this.tlsClientCertFile);\n        }\n        return chaincodeServerProperties;\n    }\n\n    /**\n     * create NettyChannel for host:port with tls if tlsEnabled.\n     *\n     * @return ManagedChannelBuilder\n     * @throws IOException while createSSLContext()\n     */\n    @SuppressWarnings(\"deprecation\")\n    public final ManagedChannelBuilder<?> newChannelBuilder() throws IOException {\n\n        // Consider moving this to be pure GRPC\n        // This is being reworked in master so leaving this 'as-is'\n        final NettyChannelBuilder builder = NettyChannelBuilder.forAddress(host, port);\n        LOGGER.info(\"Configuring channel connection to peer.\");\n\n        builder.maxInboundMessageSize(getMaxInboundMessageSize());\n\n        if (tlsEnabled) {\n            builder.negotiationType(NegotiationType.TLS);\n            builder.sslContext(createSSLContext());\n        } else {\n            builder.usePlaintext();\n        }\n\n        // there is a optional in GRPC to use 'directExecutor' rather than the inbuilt\n        // gRPC thread management\n        // not seen to make a marked difference in performance.\n        // However if it ever does, then this is where it should be enabled\n        return builder;\n    }\n\n    final SslContext createSSLContext() throws IOException {\n        final byte[] ckb = Files.readAllBytes(Paths.get(this.tlsClientKeyPath));\n        final byte[] ccb = Files.readAllBytes(Paths.get(this.tlsClientCertPath));\n\n        return GrpcSslContexts.forClient()\n                .trustManager(new File(this.tlsClientRootCertPath))\n                .keyManager(\n                        new ByteArrayInputStream(Base64.getDecoder().decode(ccb)),\n                        new ByteArrayInputStream(Base64.getDecoder().decode(ckb)))\n                .build();\n    }\n\n    @Deprecated\n    protected static Response newSuccessResponse(final String message, final byte[] payload) {\n        return ResponseUtils.newSuccessResponse(message, payload);\n    }\n\n    @Deprecated\n    protected static Response newSuccessResponse() {\n        return ResponseUtils.newSuccessResponse();\n    }\n\n    @Deprecated\n    protected static Response newSuccessResponse(final String message) {\n        return ResponseUtils.newSuccessResponse(message);\n    }\n\n    @Deprecated\n    protected static Response newSuccessResponse(final byte[] payload) {\n        return ResponseUtils.newSuccessResponse(payload);\n    }\n\n    @Deprecated\n    protected static Response newErrorResponse(final String message, final byte[] payload) {\n        return ResponseUtils.newErrorResponse(message, payload);\n    }\n\n    @Deprecated\n    protected static Response newErrorResponse() {\n        return ResponseUtils.newErrorResponse();\n    }\n\n    @Deprecated\n    protected static Response newErrorResponse(final String message) {\n        return ResponseUtils.newErrorResponse(message);\n    }\n\n    @Deprecated\n    protected static Response newErrorResponse(final byte[] payload) {\n        return ResponseUtils.newErrorResponse(payload);\n    }\n\n    @Deprecated\n    protected static Response newErrorResponse(final Throwable throwable) {\n        return ResponseUtils.newErrorResponse(throwable);\n    }\n\n    final String getHost() {\n        return host;\n    }\n\n    final int getPort() {\n        return port;\n    }\n\n    final boolean isTlsEnabled() {\n        return tlsEnabled;\n    }\n\n    final String getTlsClientKeyPath() {\n        return tlsClientKeyPath;\n    }\n\n    final String getTlsClientCertPath() {\n        return tlsClientCertPath;\n    }\n\n    final String getTlsClientRootCertPath() {\n        return tlsClientRootCertPath;\n    }\n\n    /**\n     * Chaincode name / Chaincode id.\n     *\n     * @return string\n     */\n    String getId() {\n        return id;\n    }\n\n    /** Chaincode State. */\n    public enum CCState {\n        /** */\n        CREATED,\n        /** */\n        ESTABLISHED,\n        /** */\n        READY\n    }\n\n    /** @return State */\n    public final CCState getState() {\n        return this.state;\n    }\n\n    /** @param newState */\n    public final void setState(final CCState newState) {\n        this.state = newState;\n    }\n\n    /**\n     * Debug Message.\n     *\n     * @param message\n     * @return JSON Form of message\n     */\n    public static String toJsonString(final ChaincodeMessage message) {\n        try {\n            return JsonFormat.printer().print(message);\n        } catch (final InvalidProtocolBufferException e) {\n            return String.format(\"{ Type: %s, TxId: %s }\", message.getType(), message.getTxid());\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ChaincodeException.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim;\n\nimport static java.nio.charset.StandardCharsets.UTF_8;\n\n/**\n * Contracts should use {@code ChaincodeException} to indicate when an error occurs in Smart Contract logic.\n *\n * <p>When a {@code ChaincodeException} is thrown an error response will be returned from the chaincode container\n * containing the exception message and payload, if specified.\n *\n * <p>{@code ChaincodeException} may be extended to provide application specific error information. Subclasses should\n * ensure that {@link #getPayload} returns a serialized representation of the error in a suitable format for client\n * applications to process.\n */\npublic class ChaincodeException extends RuntimeException {\n\n    private static final long serialVersionUID = 3664437023130016393L;\n\n    private byte[] payload;\n\n    /** Constructs a new {@code ChaincodeException} with no detail message. */\n    public ChaincodeException() {\n        super();\n    }\n\n    /**\n     * Constructs a new {@code ChaincodeException} with the specified detail message.\n     *\n     * @param message the detail message.\n     */\n    public ChaincodeException(final String message) {\n        super(message);\n    }\n\n    /**\n     * Constructs a new {@code ChaincodeException} with the specified cause.\n     *\n     * @param cause the cause.\n     */\n    public ChaincodeException(final Throwable cause) {\n        super(cause);\n    }\n\n    /**\n     * Constructs a new {@code ChaincodeException} with the specified detail message and cause.\n     *\n     * @param message the detail message.\n     * @param cause the cause.\n     */\n    public ChaincodeException(final String message, final Throwable cause) {\n        super(message, cause);\n    }\n\n    /**\n     * Constructs a new {@code ChaincodeException} with the specified detail message and response payload.\n     *\n     * @param message the detail message.\n     * @param payload the response payload.\n     */\n    @SuppressWarnings(\"PMD.ArrayIsStoredDirectly\")\n    public ChaincodeException(final String message, final byte[] payload) {\n        super(message);\n\n        this.payload = payload;\n    }\n\n    /**\n     * Constructs a new {@code ChaincodeException} with the specified detail message, response payload and cause.\n     *\n     * @param message the detail message.\n     * @param payload the response payload.\n     * @param cause the cause.\n     */\n    @SuppressWarnings(\"PMD.ArrayIsStoredDirectly\")\n    public ChaincodeException(final String message, final byte[] payload, final Throwable cause) {\n        super(message, cause);\n\n        this.payload = payload;\n    }\n\n    /**\n     * Constructs a new {@code ChaincodeException} with the specified detail message and response payload.\n     *\n     * @param message the detail message.\n     * @param payload the response payload.\n     */\n    public ChaincodeException(final String message, final String payload) {\n        super(message);\n\n        this.payload = payload.getBytes(UTF_8);\n    }\n\n    /**\n     * Constructs a new {@code ChaincodeException} with the specified detail message, response payload and cause.\n     *\n     * @param message the detail message.\n     * @param payload the response payload.\n     * @param cause the cause.\n     */\n    public ChaincodeException(final String message, final String payload, final Throwable cause) {\n        super(message, cause);\n\n        this.payload = payload.getBytes(UTF_8);\n    }\n\n    /**\n     * Returns the response payload or {@code null} if there is no response.\n     *\n     * <p>The payload should represent the chaincode error in a way that client applications written in different\n     * programming languages can interpret. For example it could include a domain specific error code, in addition to\n     * any state information which would allow client applications to respond appropriately.\n     *\n     * @return the response payload or {@code null} if there is no response.\n     */\n    @SuppressWarnings(\"PMD.MethodReturnsInternalArray\")\n    public byte[] getPayload() {\n        return payload;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ChaincodeServer.java",
    "content": "/*\n * Copyright 2020 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim;\n\nimport java.io.IOException;\n\n/** External chaincode server. */\npublic interface ChaincodeServer {\n\n    /**\n     * run external chaincode server.\n     *\n     * @throws IOException problem while start grpc server\n     * @throws InterruptedException thrown when block and awaiting shutdown gprc server\n     */\n    void start() throws IOException, InterruptedException;\n\n    /** shutdown now grpc server. */\n    void stop();\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ChaincodeServerProperties.java",
    "content": "/*\n * Copyright 2020 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim;\n\nimport java.net.SocketAddress;\n\npublic final class ChaincodeServerProperties {\n    private SocketAddress serverAddress;\n    private int maxInboundMetadataSize = 100 * 1024 * 1024;\n    private int maxInboundMessageSize = 100 * 1024 * 1024;\n    private int maxConnectionAgeSeconds = 5;\n    private int keepAliveTimeoutSeconds = 20;\n    private int permitKeepAliveTimeMinutes = 1;\n    private int keepAliveTimeMinutes = 1;\n    private boolean permitKeepAliveWithoutCalls = true;\n    private String keyPassword;\n    private String keyCertChainFile;\n    private String keyFile;\n    private String trustCertCollectionFile;\n    private boolean tlsEnabled;\n\n    /** Constructor using default configuration. */\n    public ChaincodeServerProperties() {\n        // Nothing to do\n    }\n\n    /**\n     * Constructor.\n     *\n     * @param portChaincodeServer ignored.\n     * @param maxInboundMetadataSize the maximum metadata size allowed to be received by the server.\n     * @param maxInboundMessageSize the maximum message size allowed to be received by the server.\n     * @param maxConnectionAgeSeconds the maximum connection age in seconds.\n     * @param keepAliveTimeoutSeconds timeout for a keep-alive ping request in seconds.\n     * @param permitKeepAliveTimeMinutes the most aggressive keep-alive time clients are permitted to configure in\n     *     minutes.\n     * @param keepAliveTimeMinutes delay before server sends a keep-alive in minutes.\n     * @param permitKeepAliveWithoutCalls whether clients are allowed to send keep-alive HTTP/2 PINGs even if there are\n     *     no outstanding RPCs on the connection.\n     */\n    @SuppressWarnings({\"PMD.NullAssignment\"})\n    public ChaincodeServerProperties(\n            final int portChaincodeServer,\n            final int maxInboundMetadataSize,\n            final int maxInboundMessageSize,\n            final int maxConnectionAgeSeconds,\n            final int keepAliveTimeoutSeconds,\n            final int permitKeepAliveTimeMinutes,\n            final int keepAliveTimeMinutes,\n            final boolean permitKeepAliveWithoutCalls) {\n\n        this.serverAddress = null;\n        this.maxInboundMetadataSize = maxInboundMetadataSize;\n        this.maxInboundMessageSize = maxInboundMessageSize;\n        this.maxConnectionAgeSeconds = maxConnectionAgeSeconds;\n        this.keepAliveTimeoutSeconds = keepAliveTimeoutSeconds;\n        this.permitKeepAliveTimeMinutes = permitKeepAliveTimeMinutes;\n        this.keepAliveTimeMinutes = keepAliveTimeMinutes;\n        this.permitKeepAliveWithoutCalls = permitKeepAliveWithoutCalls;\n    }\n\n    /**\n     * The maximum size of metadata allowed to be received.\n     *\n     * @return The maximum metadata size allowed.\n     */\n    public int getMaxInboundMetadataSize() {\n        return maxInboundMetadataSize;\n    }\n\n    /**\n     * Sets the maximum metadata size allowed to be received by the server.\n     *\n     * @param maxInboundMetadataSize The new maximum size allowed for incoming metadata.\n     */\n    public void setMaxInboundMetadataSize(final int maxInboundMetadataSize) {\n        this.maxInboundMetadataSize = maxInboundMetadataSize;\n    }\n\n    /**\n     * The maximum message size allowed to be received by the server.\n     *\n     * @return the maximum message size allowed.\n     */\n    public int getMaxInboundMessageSize() {\n        return maxInboundMessageSize;\n    }\n\n    /**\n     * Sets the maximum message size allowed to be received by the server.\n     *\n     * @param maxInboundMessageSize The new maximum size allowed for incoming messages.\n     */\n    public void setMaxInboundMessageSize(final int maxInboundMessageSize) {\n        this.maxInboundMessageSize = maxInboundMessageSize;\n    }\n\n    /**\n     * The maximum connection age.\n     *\n     * @return The maximum connection age in seconds.\n     */\n    public int getMaxConnectionAgeSeconds() {\n        return maxConnectionAgeSeconds;\n    }\n\n    /**\n     * Specify a maximum connection age.\n     *\n     * @param maxConnectionAgeSeconds The maximum connection age in seconds.\n     */\n    public void setMaxConnectionAgeSeconds(final int maxConnectionAgeSeconds) {\n        this.maxConnectionAgeSeconds = maxConnectionAgeSeconds;\n    }\n\n    /**\n     * The timeout for a keep-alive ping requests.\n     *\n     * @return timeout in seconds.\n     */\n    public int getKeepAliveTimeoutSeconds() {\n        return keepAliveTimeoutSeconds;\n    }\n\n    /**\n     * Set the timeout for keep-alive ping requests.\n     *\n     * @param keepAliveTimeoutSeconds timeout in seconds.\n     */\n    public void setKeepAliveTimeoutSeconds(final int keepAliveTimeoutSeconds) {\n        this.keepAliveTimeoutSeconds = keepAliveTimeoutSeconds;\n    }\n\n    /**\n     * The most aggressive keep-alive time clients are permitted to configure.\n     *\n     * @return time in minutes.\n     */\n    public int getPermitKeepAliveTimeMinutes() {\n        return permitKeepAliveTimeMinutes;\n    }\n\n    /**\n     * Specify the most aggressive keep-alive time clients are permitted to configure.\n     *\n     * @param permitKeepAliveTimeMinutes time in minutes.\n     */\n    public void setPermitKeepAliveTimeMinutes(final int permitKeepAliveTimeMinutes) {\n        this.permitKeepAliveTimeMinutes = permitKeepAliveTimeMinutes;\n    }\n\n    /**\n     * The delay before the server sends a keep-alive.\n     *\n     * @return delay in minutes.\n     */\n    public int getKeepAliveTimeMinutes() {\n        return keepAliveTimeMinutes;\n    }\n\n    /**\n     * Set the delay before the server sends a keep-alive.\n     *\n     * @param keepAliveTimeMinutes delay in minutes.\n     */\n    public void setKeepAliveTimeMinutes(final int keepAliveTimeMinutes) {\n        this.keepAliveTimeMinutes = keepAliveTimeMinutes;\n    }\n\n    /**\n     * Whether clients are allowed to send keep-alive HTTP/2 PINGs even if there are no outstanding RPCs on the\n     * connection.\n     *\n     * @return true if clients are allowed to send keep-alive requests without calls; otherwise false.\n     */\n    @SuppressWarnings(\"PMD.BooleanGetMethodName\")\n    public boolean getPermitKeepAliveWithoutCalls() {\n        return permitKeepAliveWithoutCalls;\n    }\n\n    /**\n     * Get the server socket address.\n     *\n     * @return a socket address.\n     */\n    public SocketAddress getServerAddress() {\n        return serverAddress;\n    }\n\n    /**\n     * Set the server socket address.\n     *\n     * @param address a socket address.\n     */\n    public void setServerAddress(final SocketAddress address) {\n        this.serverAddress = address;\n    }\n\n    /**\n     * Whether clients are allowed to send keep-alive HTTP/2 PINGs even if there are no outstanding RPCs on the\n     * connection.\n     *\n     * @return true if clients are allowed to send keep-alive requests without calls; otherwise false.\n     */\n    public boolean isPermitKeepAliveWithoutCalls() {\n        return permitKeepAliveWithoutCalls;\n    }\n\n    /**\n     * Specify whether clients are allowed to send keep-alive HTTP/2 PINGs even if there are no outstanding RPCs on the\n     * connection.\n     *\n     * @param permitKeepAliveWithoutCalls Whether to allow clients to send keep-alive requests without calls.\n     */\n    public void setPermitKeepAliveWithoutCalls(final boolean permitKeepAliveWithoutCalls) {\n        this.permitKeepAliveWithoutCalls = permitKeepAliveWithoutCalls;\n    }\n\n    /**\n     * Password used to access the server key.\n     *\n     * @return a password.\n     */\n    public String getKeyPassword() {\n        return keyPassword;\n    }\n\n    /**\n     * Set the password used to access the server key.\n     *\n     * @param keyPassword a password.\n     */\n    public void setKeyPassword(final String keyPassword) {\n        this.keyPassword = keyPassword;\n    }\n\n    /**\n     * Server keychain file name.\n     *\n     * @return a file name.\n     */\n    public String getKeyCertChainFile() {\n        return keyCertChainFile;\n    }\n\n    /**\n     * Set the server keychain file name.\n     *\n     * @param keyCertChainFile a file name.\n     */\n    public void setKeyCertChainFile(final String keyCertChainFile) {\n        this.keyCertChainFile = keyCertChainFile;\n    }\n\n    /**\n     * Server key file name.\n     *\n     * @return a file name.\n     */\n    public String getKeyFile() {\n        return keyFile;\n    }\n\n    /**\n     * Set the server key file name.\n     *\n     * @param keyFile a file name.\n     */\n    public void setKeyFile(final String keyFile) {\n        this.keyFile = keyFile;\n    }\n\n    /**\n     * Server trust certificate collection file name.\n     *\n     * @return a file name.\n     */\n    public String getTrustCertCollectionFile() {\n        return trustCertCollectionFile;\n    }\n\n    /**\n     * Set the server trust certificate collection file name.\n     *\n     * @param trustCertCollectionFile a file name.\n     */\n    public void setTrustCertCollectionFile(final String trustCertCollectionFile) {\n        this.trustCertCollectionFile = trustCertCollectionFile;\n    }\n\n    /**\n     * Whether TLS is enabled for the server.\n     *\n     * @return true if TLS is enabled; otherwise false.\n     */\n    public boolean isTlsEnabled() {\n        return tlsEnabled;\n    }\n\n    /**\n     * Set whether TLS is enabled for the server.\n     *\n     * @param tlsEnabled true to enable TLS; otherwise false.\n     */\n    public void setTlsEnabled(final boolean tlsEnabled) {\n        this.tlsEnabled = tlsEnabled;\n    }\n\n    /**\n     * Check that all the server property values are valid.\n     *\n     * @throws IllegalArgumentException if any properties are not valid.\n     */\n    @SuppressWarnings(\"PMD.CyclomaticComplexity\")\n    public void validate() {\n        if (this.getServerAddress() == null) {\n            throw new IllegalArgumentException(\"chaincodeServerProperties.getServerAddress() must be set\");\n        }\n        if (this.getKeepAliveTimeMinutes() <= 0) {\n            throw new IllegalArgumentException(\n                    \"chaincodeServerProperties.getKeepAliveTimeMinutes() must be more then 0\");\n        }\n        if (this.getKeepAliveTimeoutSeconds() <= 0) {\n            throw new IllegalArgumentException(\n                    \"chaincodeServerProperties.getKeepAliveTimeoutSeconds() must be more then 0\");\n        }\n        if (this.getPermitKeepAliveTimeMinutes() <= 0) {\n            throw new IllegalArgumentException(\n                    \"chaincodeServerProperties.getPermitKeepAliveTimeMinutes() must be more then 0\");\n        }\n        if (this.getMaxConnectionAgeSeconds() <= 0) {\n            throw new IllegalArgumentException(\n                    \"chaincodeServerProperties.getMaxConnectionAgeSeconds() must be more then 0\");\n        }\n        if (this.getMaxInboundMetadataSize() <= 0) {\n            throw new IllegalArgumentException(\n                    \"chaincodeServerProperties.getMaxInboundMetadataSize() must be more then 0\");\n        }\n        if (this.getMaxInboundMessageSize() <= 0) {\n            throw new IllegalArgumentException(\n                    \"chaincodeServerProperties.getMaxInboundMessageSize() must be more then 0\");\n        }\n        if (this.isTlsEnabled()\n                && (this.getKeyCertChainFile() == null\n                        || this.getKeyCertChainFile().isEmpty()\n                        || this.getKeyFile() == null\n                        || this.getKeyFile().isEmpty())) {\n            throw new IllegalArgumentException(\"if chaincodeServerProperties.isTlsEnabled() must be more specified\"\n                    + \" chaincodeServerProperties.getKeyCertChainFile() and chaincodeServerProperties.getKeyFile()\"\n                    + \" with optional chaincodeServerProperties.getKeyPassword()\");\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ChaincodeStub.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim;\n\nimport static java.nio.charset.StandardCharsets.UTF_8;\nimport static java.util.stream.Collectors.toList;\n\nimport java.time.Instant;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport org.hyperledger.fabric.protos.peer.ChaincodeEvent;\nimport org.hyperledger.fabric.protos.peer.SignedProposal;\nimport org.hyperledger.fabric.shim.Chaincode.Response;\nimport org.hyperledger.fabric.shim.ledger.CompositeKey;\nimport org.hyperledger.fabric.shim.ledger.KeyModification;\nimport org.hyperledger.fabric.shim.ledger.KeyValue;\nimport org.hyperledger.fabric.shim.ledger.QueryResultsIterator;\nimport org.hyperledger.fabric.shim.ledger.QueryResultsIteratorWithMetadata;\n\n/**\n * An object which manages the transaction context, provides access to state variables, and supports calls to other\n * chaincode implementations.\n */\n@SuppressWarnings(\"PMD.ExcessivePublicCount\")\npublic interface ChaincodeStub {\n\n    /**\n     * Returns the arguments corresponding to the call to {@link Chaincode#init(ChaincodeStub)} or\n     * {@link Chaincode#invoke(ChaincodeStub)}, each argument represented as byte array.\n     *\n     * @return a list of arguments (bytes arrays)\n     */\n    List<byte[]> getArgs();\n\n    /**\n     * Returns the arguments corresponding to the call to {@link Chaincode#init(ChaincodeStub)} or\n     * {@link Chaincode#invoke(ChaincodeStub)}, cast to UTF-8 string.\n     *\n     * @return a list of arguments cast to UTF-8 strings\n     */\n    List<String> getStringArgs();\n\n    /**\n     * A convenience method that returns the first argument of the chaincode invocation for use as a function name.\n     *\n     * <p>The bytes of the first argument are decoded as a UTF-8 string.\n     *\n     * @return the function name\n     */\n    String getFunction();\n\n    /**\n     * A convenience method that returns all except the first argument of the chaincode invocation for use as the\n     * parameters to the function returned by #{@link ChaincodeStub#getFunction()}.\n     *\n     * <p>The bytes of the arguments are decoded as a UTF-8 strings and returned as a list of string parameters.\n     *\n     * @return a list of parameters\n     */\n    List<String> getParameters();\n\n    /**\n     * Returns the transaction id for the current chaincode invocation request.\n     *\n     * <p>The transaction id uniquely identifies the transaction within the scope of the channel.\n     *\n     * @return the transaction id\n     */\n    String getTxId();\n\n    /**\n     * Returns the channel id for the current proposal.\n     *\n     * <p>This would be the 'channel_id' of the transaction proposal except where the chaincode is calling another on a\n     * different channel.\n     *\n     * @return the channel id\n     */\n    String getChannelId();\n\n    /**\n     * Locally calls the specified chaincode <code>invoke()</code> using the same transaction context.\n     *\n     * <p>chaincode calling chaincode doesn't create a new transaction message.\n     *\n     * <p>If the called chaincode is on the same channel, it simply adds the called chaincode read set and write set to\n     * the calling transaction.\n     *\n     * <p>If the called chaincode is on a different channel, only the Response is returned to the calling chaincode; any\n     * <code>putState</code> calls from the called chaincode will not have any effect on the ledger; that is, the called\n     * chaincode on a different channel will not have its read set and write set applied to the transaction. Only the\n     * calling chaincode's read set and write set will be applied to the transaction. Effectively the called chaincode\n     * on a different channel is a `Query`, which does not participate in state validation checks in subsequent commit\n     * phase.\n     *\n     * <p>If `channel` is empty, the caller's channel is assumed.\n     *\n     * <p>Invoke another chaincode using the same transaction context.\n     *\n     * @param chaincodeName Name of chaincode to be invoked.\n     * @param args Arguments to pass on to the called chaincode.\n     * @param channel If not specified, the caller's channel is assumed.\n     * @return {@link Response} object returned by called chaincode\n     */\n    Response invokeChaincode(String chaincodeName, List<byte[]> args, String channel);\n\n    /**\n     * Returns the value of the specified <code>key</code> from the ledger.\n     *\n     * <p>Note that getState doesn't read data from the writeset, which has not been committed to the ledger. In other\n     * words, GetState doesn't consider data modified by PutState that has not been committed.\n     *\n     * @param key name of the value\n     * @return value the value read from the ledger\n     */\n    byte[] getState(String key);\n\n    /**\n     * retrieves the key-level endorsement policy for <code>key</code>. Note that this will introduce a read dependency\n     * on <code>key</code> in the transaction's readset.\n     *\n     * @param key key to get key level endorsement\n     * @return endorsement policy\n     */\n    byte[] getStateValidationParameter(String key);\n\n    /**\n     * Puts the specified <code>key</code> and <code>value</code> into the transaction's writeset as a data-write\n     * proposal.\n     *\n     * <p>putState doesn't effect the ledger until the transaction is validated and successfully committed. Simple keys\n     * must not be an empty string and must not start with 0x00 character, in order to avoid range query collisions with\n     * composite keys\n     *\n     * @param key name of the value\n     * @param value the value to write to the ledger\n     */\n    void putState(String key, byte[] value);\n\n    /**\n     * Sets the key-level endorsement policy for <code>key</code>.\n     *\n     * @param key key to set key level endorsement\n     * @param value endorsement policy\n     */\n    void setStateValidationParameter(String key, byte[] value);\n\n    /**\n     * Records the specified <code>key</code> to be deleted in the writeset of the transaction proposal.\n     *\n     * <p>The <code>key</code> and its value will be deleted from the ledger when the transaction is validated and\n     * successfully committed.\n     *\n     * @param key name of the value to be deleted\n     */\n    void delState(String key);\n\n    /**\n     * Returns all existing keys, and their values, that are lexicographically between <code>startkey</code> (inclusive)\n     * and the <code>endKey</code> (exclusive).\n     *\n     * <p>The keys are returned by the iterator in lexical order. Note that startKey and endKey can be empty string,\n     * which implies unbounded range query on start or end.\n     *\n     * <p>Call close() on the returned {@link QueryResultsIterator#close()} object when done.\n     *\n     * @param startKey key as the start of the key range (inclusive)\n     * @param endKey key as the end of the key range (exclusive)\n     * @return an {@link Iterable} of {@link KeyValue}\n     */\n    QueryResultsIterator<KeyValue> getStateByRange(String startKey, String endKey);\n\n    /**\n     * Returns a range iterator over a set of keys in the ledger. The iterator can be used to fetch keys between the\n     * <code>startKey</code> (inclusive) and <code>endKey</code> (exclusive). When an empty string is passed as a value\n     * to the <code>bookmark</code> argument, the returned iterator can be used to fetch the first <code>pageSize</code>\n     * keys between the <code>startKey</code> and <code>endKey</code>. When the <code>bookmark</code> is a non-empty\n     * string, the iterator can be used to fetch first <code>pageSize</code> keys between the <code>bookmark</code> and\n     * <code>endKey</code>. Note that only the bookmark present in a prior page of query results\n     * ({@link org.hyperledger.fabric.protos.peer.QueryResponseMetadata}) can be used as a value to the bookmark\n     * argument. Otherwise, an empty string must be passed as bookmark. The keys are returned by the iterator in lexical\n     * order. Note that <code>startKey</code> and <code>endKey</code> can be empty string, which implies unbounded range\n     * query on start or end. This call is only supported in a read only transaction.\n     *\n     * @param startKey the start key\n     * @param endKey the end key\n     * @param pageSize the page size\n     * @param bookmark the bookmark\n     * @return QueryIterator\n     */\n    QueryResultsIteratorWithMetadata<KeyValue> getStateByRangeWithPagination(\n            String startKey, String endKey, int pageSize, String bookmark);\n\n    /**\n     * Returns all existing keys, and their values, that are prefixed by the specified partial {@link CompositeKey}.\n     *\n     * <p>If a full composite key is specified, it will not match itself, resulting in no keys being returned.\n     *\n     * <p>This method takes responsibility to correctly parse the {@link CompositeKey} from a String and behaves exactly\n     * as {@link ChaincodeStub#getStateByPartialCompositeKey(CompositeKey)}.\n     *\n     * <p>Call close() on the returned {@link QueryResultsIterator#close()} object when done.\n     *\n     * @param compositeKey partial composite key\n     * @return an {@link Iterable} of {@link KeyValue}\n     */\n    QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(String compositeKey);\n\n    /**\n     * Returns all existing keys, and their values, that are prefixed by the specified partial {@link CompositeKey}.\n     *\n     * <p>It combines the attributes and the objectType to form a partial composite key.\n     *\n     * <p>If a full composite key is specified, it will not match itself, resulting in no keys being returned.\n     *\n     * <p>This method takes responsibility to correctly combine Object type and attributes creating a\n     * {@link CompositeKey} and behaves exactly as {@link ChaincodeStub#getStateByPartialCompositeKey(CompositeKey)}.\n     * Call close() on the returned {@link QueryResultsIterator#close()} object when done.\n     *\n     * @param objectType ObjectType of the compositeKey\n     * @param attributes Attributes of the composite key\n     * @return an {@link Iterable} of {@link KeyValue}\n     */\n    QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(String objectType, String... attributes);\n\n    /**\n     * Returns all existing keys, and their values, that are prefixed by the specified partial {@link CompositeKey}.\n     *\n     * <p>If a full composite key is specified, it will not match itself, resulting in no keys being returned.\n     *\n     * @param compositeKey partial composite key\n     * @return an {@link Iterable} of {@link KeyValue}\n     */\n    QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(CompositeKey compositeKey);\n\n    /**\n     * Queries the state in the ledger based on a given partial composite key. This function returns an iterator which\n     * can be used to iterate over the composite keys whose prefix matches the given partial composite key.\n     *\n     * <p>When an empty string is passed as a value to the <code>bookmark</code> argument, the returned iterator can be\n     * used to fetch the first <code>pageSize</code> composite keys whose prefix matches the given partial composite\n     * key.\n     *\n     * <p>When the <code>bookmark</code> is a non-empty string, the iterator can be used to fetch first <code>pageSize\n     * </code> keys between the <code>bookmark</code> (inclusive) and and the last matching composite key.\n     *\n     * <p>Note that only the bookmark present in a prior page of query results\n     * ({@link org.hyperledger.fabric.protos.peer.QueryResponseMetadata}) can be used as a value to the bookmark\n     * argument. Otherwise, an empty string must be passed as bookmark.\n     *\n     * <p>This call is only supported in a read only transaction.\n     *\n     * @param compositeKey the composite key\n     * @param pageSize the page size\n     * @param bookmark the bookmark\n     * @return QueryIterator\n     */\n    QueryResultsIteratorWithMetadata<KeyValue> getStateByPartialCompositeKeyWithPagination(\n            CompositeKey compositeKey, int pageSize, String bookmark);\n\n    /**\n     * Given a set of attributes, this method combines these attributes to return a composite key.\n     *\n     * @param objectType A string used as the prefix of the resulting key\n     * @param attributes List of attribute values to concatenate into the key\n     * @return a composite key\n     */\n    CompositeKey createCompositeKey(String objectType, String... attributes);\n\n    /**\n     * Parses a composite key {@link CompositeKey} from a string.\n     *\n     * @param compositeKey a composite key string\n     * @return a composite key\n     */\n    CompositeKey splitCompositeKey(String compositeKey);\n\n    /**\n     * Performs a \"rich\" query against a state database.\n     *\n     * <p>It is only supported for state databases that support rich query, e.g. CouchDB. The query string is in the\n     * native syntax of the underlying state database. An {@link QueryResultsIterator} is returned which can be used to\n     * iterate (next) over the query result set.\n     *\n     * @param query query string in a syntax supported by the underlying state database\n     * @return {@link QueryResultsIterator} object contains query results\n     * @throws UnsupportedOperationException if the underlying state database does not support rich queries.\n     */\n    QueryResultsIterator<KeyValue> getQueryResult(String query);\n\n    /**\n     * Performs a \"rich\" query against a state database. It is only supported for state databases that support rich\n     * query, e.g., CouchDB. The query string is in the native syntax of the underlying state database. An iterator is\n     * returned which can be used to iterate over keys in the query result set. When an empty string is passed as a\n     * value to the <code>bookmark</code> argument, the returned iterator can be used to fetch the first <code>pageSize\n     * </code> of query results..\n     *\n     * <p>When the <code>bookmark</code> is a non-empty string, the iterator can be used to fetch first <code>pageSize\n     * </code> keys between the <code>bookmark</code> (inclusive) and the last key in the query result.\n     *\n     * <p>Note that only the bookmark present in a prior page of query results\n     * ({@link org.hyperledger.fabric.protos.peer.QueryResponseMetadata}) can be used as a value to the bookmark\n     * argument. Otherwise, an empty string must be passed as bookmark.\n     *\n     * <p>This call is only supported in a read only transaction.\n     *\n     * @param query the query\n     * @param pageSize the page size\n     * @param bookmark the bookmark\n     * @return QueryIterator\n     */\n    QueryResultsIteratorWithMetadata<KeyValue> getQueryResultWithPagination(\n            String query, int pageSize, String bookmark);\n\n    /**\n     * Returns a history of key values across time.\n     *\n     * <p>For each historic key update, the historic value and associated transaction id and timestamp are returned. The\n     * timestamp is the timestamp provided by the client in the proposal header. This method requires peer configuration\n     * <code>core.ledger.history.enableHistoryDatabase</code> to be true.\n     *\n     * @param key The state variable key\n     * @return an {@link Iterable} of {@link KeyModification}\n     */\n    QueryResultsIterator<KeyModification> getHistoryForKey(String key);\n\n    /**\n     * Returns the value of the specified <code>key</code> from the specified <code>collection</code>.\n     *\n     * <p>Note that {@link #getPrivateData(String, String)} doesn't read data from the private writeset, which has not\n     * been committed to the <code>collection</code>. In other words, {@link #getPrivateData(String, String)} doesn't\n     * consider data modified by {@link #putPrivateData(String, String, byte[])} * that has not been committed.\n     *\n     * @param collection name of the collection\n     * @param key name of the value\n     * @return value the value read from the collection\n     */\n    byte[] getPrivateData(String collection, String key);\n\n    /**\n     * @param collection name of the collection\n     * @param key name of the value\n     * @return the private data hash\n     */\n    byte[] getPrivateDataHash(String collection, String key);\n\n    /**\n     * Retrieves the key-level endorsement policy for the private data specified by <code>key</code>. Note that this\n     * introduces a read dependency on <code>key</code> in the transaction's readset.\n     *\n     * @param collection name of the collection\n     * @param key key to get endorsement policy\n     * @return Key Level endorsement as byte array\n     */\n    byte[] getPrivateDataValidationParameter(String collection, String key);\n\n    /**\n     * Puts the specified <code>key</code> and <code>value</code> into the transaction's private writeset.\n     *\n     * <p>Note that only hash of the private writeset goes into the transaction proposal response (which is sent to the\n     * client who issued the transaction) and the actual private writeset gets temporarily stored in a transient store.\n     * putPrivateData doesn't effect the <code>collection</code> until the transaction is validated and successfully\n     * committed. Simple keys must not be an empty string and must not start with null character (0x00), in order to\n     * avoid range query collisions with composite keys, which internally get prefixed with 0x00 as composite key\n     * namespace.\n     *\n     * @param collection name of the collection\n     * @param key name of the value\n     * @param value the value to write to the ledger\n     */\n    void putPrivateData(String collection, String key, byte[] value);\n\n    /**\n     * Sets the key-level endorsement policy for the private data specified by <code>key</code>.\n     *\n     * @param collection name of the collection\n     * @param key key to set endorsement policy\n     * @param value endorsement policy\n     */\n    void setPrivateDataValidationParameter(String collection, String key, byte[] value);\n\n    /**\n     * Records the specified <code>key</code> to be deleted in the private writeset of the transaction.\n     *\n     * <p>Note that only hash of the private writeset goes into the transaction proposal response (which is sent to the\n     * client who issued the transaction) and the actual private writeset gets temporarily stored in a transient store.\n     * The <code>key</code> and its value will be deleted from the collection when the transaction is validated and\n     * successfully committed.\n     *\n     * @param collection name of the collection\n     * @param key name of the value to be deleted\n     */\n    void delPrivateData(String collection, String key);\n\n    /**\n     * Reqauests purging of the specified <code>key</code> to be from the private data stores.\n     *\n     * <p>Note that only hash of the private writeset goes into the transaction proposal response (which is sent to the\n     * client who issued the transaction) and the actual private writeset gets temporarily stored in a transient store.\n     * The <code>key</code> and its value will be purged from the collection. This is an asynchronous activity.\n     *\n     * <p>Purge is a complete removal of the history of the key. There is existing purge possible mased on block height.\n     * This API allows the contract to be pro-active in requesting data be purged. This can contribute towards meeting\n     * privacy requirements.\n     *\n     * @param collection name of the collection\n     * @param key name of the value to be deleted\n     */\n    void purgePrivateData(String collection, String key);\n\n    /**\n     * Returns all existing keys, and their values, that are lexicographically between <code>startkey</code> (inclusive)\n     * and the <code>endKey</code> (exclusive) in a given private collection.\n     *\n     * <p>Note that startKey and endKey can be empty string, which implies unbounded range query on start or end. The\n     * query is re-executed during validation phase to ensure result set has not changed since transaction endorsement\n     * (phantom reads detected).\n     *\n     * @param collection name of the collection\n     * @param startKey private data variable key as the start of the key range (inclusive)\n     * @param endKey private data variable key as the end of the key range (exclusive)\n     * @return an {@link Iterable} of {@link KeyValue}\n     */\n    QueryResultsIterator<KeyValue> getPrivateDataByRange(String collection, String startKey, String endKey);\n\n    /**\n     * Returns all existing keys, and their values, that are prefixed by the specified partial {@link CompositeKey} in a\n     * given private collection.\n     *\n     * <p>If a full composite key is specified, it will not match itself, resulting in no keys being returned.\n     *\n     * <p>The query is re-executed during validation phase to ensure result set has not changed since transaction\n     * endorsement (phantom reads detected).\n     *\n     * <p>This method takes responsibility to correctly parse the {@link CompositeKey} from a String and behaves exactly\n     * as {@link ChaincodeStub#getPrivateDataByPartialCompositeKey(String, CompositeKey)}.\n     *\n     * @param collection name of the collection\n     * @param compositeKey partial composite key\n     * @return an {@link Iterable} of {@link KeyValue}\n     */\n    QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(String collection, String compositeKey);\n\n    /**\n     * Returns all existing keys, and their values, that are prefixed by the specified partial {@link CompositeKey} in a\n     * given private collection.\n     *\n     * <p>If a full composite key is specified, it will not match itself, resulting in no keys being returned.\n     *\n     * <p>The query is re-executed during validation phase to ensure result set has not changed since transaction\n     * endorsement (phantom reads detected).\n     *\n     * @param collection name of the collection\n     * @param compositeKey partial composite key\n     * @return an {@link Iterable} of {@link KeyValue}\n     */\n    QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(String collection, CompositeKey compositeKey);\n\n    /**\n     * Returns all existing keys, and their values, that are prefixed by the specified partial {@link CompositeKey} in a\n     * given private collection.\n     *\n     * <p>If a full composite key is specified, it will not match itself, resulting in no keys being returned.\n     *\n     * <p>The query is re-executed during validation phase to ensure result set has not changed since transaction\n     * endorsement (phantom reads detected).\n     *\n     * <p>This method takes responsibility to correctly combine Object type and attributes creating a\n     * {@link CompositeKey} and behaves exactly as {@link ChaincodeStub#getPrivateDataByPartialCompositeKey(String,\n     * CompositeKey)}.\n     *\n     * @param collection name of the collection\n     * @param objectType ObjectType of the compositeKey\n     * @param attributes Attributes of the composite key\n     * @return an {@link Iterable} of {@link KeyValue}\n     */\n    QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(\n            String collection, String objectType, String... attributes);\n\n    /**\n     * Perform a rich query against a given private collection.\n     *\n     * <p>It is only supported for state databases that support rich query, e.g.CouchDB. The query string is in the\n     * native syntax of the underlying state database. An iterator is returned which can be used to iterate (next) over\n     * the query result set. The query is NOT re-executed during validation phase, phantom reads are not detected. That\n     * is, other committed transactions may have added, updated, or removed keys that impact the result set, and this\n     * would not be detected at validation/commit time. Applications susceptible to this should therefore not use\n     * GetQueryResult as part of transactions that update ledger, and should limit use to read-only chaincode\n     * operations.\n     *\n     * @param collection name of the collection\n     * @param query query string in a syntax supported by the underlying state database\n     * @return {@link QueryResultsIterator} object contains query results\n     * @throws UnsupportedOperationException if the underlying state database does not support rich queries.\n     */\n    QueryResultsIterator<KeyValue> getPrivateDataQueryResult(String collection, String query);\n\n    /**\n     * Allows the chaincode to propose an event on the transaction proposal response. When the transaction is included\n     * in a block and the block is successfully committed to the ledger, the block event (including transaction level\n     * chaincode events) will be delivered to the current client application event listeners that have been registered\n     * with the peer's event producer. Consult each SDK's documentation for details. Only a single chaincode event can\n     * be included in a transaction. If setEvent() is called multiple times only the last event will be included in the\n     * transaction. The event must originate from the outer-most invoked chaincode in chaincode-to-chaincode scenarios.\n     * The marshaled ChaincodeEvent will be available in the transaction's ChaincodeAction.events field.\n     *\n     * @param name Name of event. Cannot be null or empty string.\n     * @param payload Optional event payload.\n     */\n    void setEvent(String name, byte[] payload);\n\n    /**\n     * Invoke another chaincode using the same transaction context.\n     *\n     * <p>Same as {@link #invokeChaincode(String, List, String)} using channelId to <code>null</code>\n     *\n     * @param chaincodeName Name of chaincode to be invoked.\n     * @param args Arguments to pass on to the called chaincode.\n     * @return {@link Response} object returned by called chaincode\n     */\n    default Response invokeChaincode(final String chaincodeName, final List<byte[]> args) {\n        return invokeChaincode(chaincodeName, args, null);\n    }\n\n    /**\n     * Invoke another chaincode using the same transaction context.\n     *\n     * <p>This is a convenience version of {@link #invokeChaincode(String, List, String)}. The string args will be\n     * encoded into as UTF-8 bytes.\n     *\n     * @param chaincodeName Name of chaincode to be invoked.\n     * @param args Arguments to pass on to the called chaincode.\n     * @param channel If not specified, the caller's channel is assumed.\n     * @return {@link Response} object returned by called chaincode\n     */\n    default Response invokeChaincodeWithStringArgs(\n            final String chaincodeName, final List<String> args, final String channel) {\n        return invokeChaincode(\n                chaincodeName, args.stream().map(x -> x.getBytes(UTF_8)).collect(toList()), channel);\n    }\n\n    /**\n     * Invoke another chaincode using the same transaction context.\n     *\n     * <p>This is a convenience version of {@link #invokeChaincode(String, List)}. The string args will be encoded into\n     * as UTF-8 bytes.\n     *\n     * @param chaincodeName Name of chaincode to be invoked.\n     * @param args Arguments to pass on to the called chaincode.\n     * @return {@link Response} object returned by called chaincode\n     */\n    default Response invokeChaincodeWithStringArgs(final String chaincodeName, final List<String> args) {\n        return invokeChaincodeWithStringArgs(chaincodeName, args, null);\n    }\n\n    /**\n     * Invoke another chaincode using the same transaction context.\n     *\n     * <p>This is a convenience version of {@link #invokeChaincode(String, List)}. The string args will be encoded into\n     * as UTF-8 bytes.\n     *\n     * @param chaincodeName Name of chaincode to be invoked.\n     * @param args Arguments to pass on to the called chaincode.\n     * @return {@link Response} object returned by called chaincode\n     */\n    default Response invokeChaincodeWithStringArgs(final String chaincodeName, final String... args) {\n        return invokeChaincodeWithStringArgs(chaincodeName, Arrays.asList(args), null);\n    }\n\n    /**\n     * Returns the byte array value specified by the key and decoded as a UTF-8 encoded string, from the ledger.\n     *\n     * <p>This is a convenience version of {@link #getState(String)}\n     *\n     * @param key name of the value\n     * @return value the value read from the ledger\n     */\n    default String getStringState(final String key) {\n        return new String(getState(key), UTF_8);\n    }\n\n    /**\n     * Writes the specified value and key into the sidedb collection value converted to byte array.\n     *\n     * @param collection collection name\n     * @param key name of the value\n     * @param value the value to write to the ledger\n     */\n    default void putPrivateData(final String collection, final String key, final String value) {\n        putPrivateData(collection, key, value.getBytes(UTF_8));\n    }\n\n    /**\n     * Returns the byte array value specified by the key and decoded as a UTF-8 encoded string, from the sidedb\n     * collection.\n     *\n     * @param collection collection name\n     * @param key name of the value\n     * @return value the value read from the ledger\n     */\n    default String getPrivateDataUTF8(final String collection, final String key) {\n        return new String(getPrivateData(collection, key), UTF_8);\n    }\n\n    /**\n     * Writes the specified value and key into the ledger.\n     *\n     * @param key name of the value\n     * @param value the value to write to the ledger\n     */\n    default void putStringState(final String key, final String value) {\n        putState(key, value.getBytes(UTF_8));\n    }\n\n    /**\n     * Returns the CHAINCODE type event that will be posted to interested clients when the chaincode's result is\n     * committed to the ledger.\n     *\n     * @return the chaincode event or null\n     */\n    ChaincodeEvent getEvent();\n\n    /**\n     * Returns the signed transaction proposal currently being executed.\n     *\n     * @return null if the current transaction is an internal call to a system chaincode.\n     */\n    SignedProposal getSignedProposal();\n\n    /**\n     * Returns the timestamp when the transaction was created.\n     *\n     * @return timestamp as specified in the transaction's channel header.\n     */\n    Instant getTxTimestamp();\n\n    /**\n     * Returns the identity of the agent (or user) submitting the transaction.\n     *\n     * @return the bytes of the creator field of the proposal's signature header.\n     */\n    byte[] getCreator();\n\n    /**\n     * Returns the transient map associated with the current transaction.\n     *\n     * @return map of transient field\n     */\n    Map<String, byte[]> getTransient();\n\n    /**\n     * Returns the transaction binding.\n     *\n     * @return binding between application data and proposal\n     */\n    byte[] getBinding();\n\n    /**\n     * Get the MSPID of the peer that started this chaincode.\n     *\n     * @return string MSPID\n     */\n    String getMspId();\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ChatChaincodeWithPeer.java",
    "content": "/*\n * Copyright 2020 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim;\n\nimport io.grpc.stub.StreamObserver;\nimport java.io.IOException;\nimport java.util.logging.Logger;\nimport org.hyperledger.fabric.Logging;\nimport org.hyperledger.fabric.protos.peer.ChaincodeGrpc;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\n\npublic class ChatChaincodeWithPeer extends ChaincodeGrpc.ChaincodeImplBase {\n    private static Logger logger = Logger.getLogger(ChatChaincodeWithPeer.class.getName());\n\n    private final ChaincodeBase chaincodeBase;\n\n    ChatChaincodeWithPeer(final ChaincodeBase chaincodeBase) throws IOException {\n        super();\n        if (chaincodeBase == null) {\n            throw new IOException(\"chaincodeBase can't be null\");\n        }\n        chaincodeBase.validateOptions();\n\n        this.chaincodeBase = chaincodeBase;\n    }\n\n    /**\n     * Chaincode as a server - peer establishes a connection to the chaincode as a client Currently only supports a\n     * stream connection.\n     *\n     * @param responseObserver\n     * @return\n     */\n    @Override\n    @SuppressWarnings(\"PMD.AvoidCatchingGenericException\")\n    public StreamObserver<ChaincodeMessage> connect(final StreamObserver<ChaincodeMessage> responseObserver) {\n        if (responseObserver == null) {\n            return null;\n        }\n\n        try {\n            return chaincodeBase.connectToPeer(responseObserver);\n        } catch (Exception e) {\n            logger.severe(() ->\n                    \"catch exception while chaincodeBase.connectToPeer(responseObserver).\" + Logging.formatError(e));\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/GrpcServer.java",
    "content": "/*\n * Copyright 2020 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim;\n\nimport java.io.IOException;\n\n/** Common interface for grpc server. */\npublic interface GrpcServer {\n\n    /**\n     * start grpc server.\n     *\n     * @throws IOException problem while start grpc server\n     */\n    void start() throws IOException;\n\n    /** shutdown now grpc server. */\n    void stop();\n\n    /**\n     * Await termination on the main thread since the grpc library uses daemon threads.\n     *\n     * @throws InterruptedException\n     */\n    void blockUntilShutdown() throws InterruptedException;\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/NettyChaincodeServer.java",
    "content": "/*\n * Copyright 2020 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim;\n\nimport java.io.IOException;\n\npublic class NettyChaincodeServer implements ChaincodeServer {\n\n    /** Server. */\n    private final GrpcServer grpcServer;\n\n    /**\n     * configure and init server.\n     *\n     * @param chaincodeBase - chaincode implementation (invoke, init)\n     * @param chaincodeServerProperties - setting for grpc server\n     * @throws IOException\n     */\n    public NettyChaincodeServer(\n            final ChaincodeBase chaincodeBase, final ChaincodeServerProperties chaincodeServerProperties)\n            throws IOException {\n        // create listener and grpc server\n        grpcServer = new NettyGrpcServer(chaincodeBase, chaincodeServerProperties);\n    }\n\n    /**\n     * run external chaincode server.\n     *\n     * @throws IOException problem while start grpc server\n     * @throws InterruptedException thrown when block and awaiting shutdown gprc server\n     */\n    @Override\n    public void start() throws IOException, InterruptedException {\n        grpcServer.start();\n        grpcServer.blockUntilShutdown();\n    }\n\n    /** shutdown now grpc server. */\n    @Override\n    public void stop() {\n        grpcServer.stop();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/NettyGrpcServer.java",
    "content": "/*\n * Copyright 2020 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim;\n\nimport io.grpc.Server;\nimport io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder;\nimport io.grpc.netty.shaded.io.netty.handler.ssl.ApplicationProtocolConfig;\nimport io.grpc.netty.shaded.io.netty.handler.ssl.ApplicationProtocolNames;\nimport io.grpc.netty.shaded.io.netty.handler.ssl.ClientAuth;\nimport io.grpc.netty.shaded.io.netty.handler.ssl.SslContextBuilder;\nimport java.io.File;\nimport java.io.IOException;\nimport java.nio.file.Paths;\nimport java.util.concurrent.TimeUnit;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport javax.net.ssl.SSLException;\n\n/** implementation grpc server with NettyGrpcServer. */\npublic final class NettyGrpcServer implements GrpcServer {\n\n    private static final Logger LOGGER = Logger.getLogger(NettyGrpcServer.class.getName());\n\n    private final Server server;\n\n    /**\n     * init netty grpc server.\n     *\n     * @param chaincodeBase - chaincode implementation (invoke, init)\n     * @param chaincodeServerProperties - setting for grpc server\n     * @throws IOException\n     */\n    public NettyGrpcServer(final ChaincodeBase chaincodeBase, final ChaincodeServerProperties chaincodeServerProperties)\n            throws IOException {\n        if (chaincodeBase == null) {\n            throw new IllegalArgumentException(\"chaincode must be specified\");\n        }\n        if (chaincodeServerProperties == null) {\n            throw new IllegalArgumentException(\"chaincodeServerProperties must be specified\");\n        }\n        chaincodeServerProperties.validate();\n\n        final NettyServerBuilder serverBuilder = NettyServerBuilder.forAddress(\n                        chaincodeServerProperties.getServerAddress())\n                .addService(new ChatChaincodeWithPeer(chaincodeBase))\n                .keepAliveTime(chaincodeServerProperties.getKeepAliveTimeMinutes(), TimeUnit.MINUTES)\n                .keepAliveTimeout(chaincodeServerProperties.getKeepAliveTimeoutSeconds(), TimeUnit.SECONDS)\n                .permitKeepAliveTime(chaincodeServerProperties.getPermitKeepAliveTimeMinutes(), TimeUnit.MINUTES)\n                .permitKeepAliveWithoutCalls(chaincodeServerProperties.isPermitKeepAliveWithoutCalls())\n                .maxConnectionAge(chaincodeServerProperties.getMaxConnectionAgeSeconds(), TimeUnit.SECONDS)\n                .maxInboundMetadataSize(chaincodeServerProperties.getMaxInboundMetadataSize())\n                .maxInboundMessageSize(chaincodeServerProperties.getMaxInboundMessageSize());\n\n        if (chaincodeServerProperties.isTlsEnabled()) {\n            configureTls(serverBuilder, chaincodeServerProperties);\n        }\n\n        if (LOGGER.isLoggable(Level.INFO)) {\n            LOGGER.info(\"<<<<<<<<<<<<<chaincodeServerProperties>>>>>>>>>>>>:\\n\");\n            LOGGER.info(\"ServerAddress:\"\n                    + chaincodeServerProperties.getServerAddress().toString());\n            LOGGER.info(\"MaxInboundMetadataSize:\" + chaincodeServerProperties.getMaxInboundMetadataSize());\n            LOGGER.info(\"MaxInboundMessageSize:\" + chaincodeServerProperties.getMaxInboundMessageSize());\n            LOGGER.info(\"MaxConnectionAgeSeconds:\" + chaincodeServerProperties.getMaxConnectionAgeSeconds());\n            LOGGER.info(\"KeepAliveTimeoutSeconds:\" + chaincodeServerProperties.getKeepAliveTimeoutSeconds());\n            LOGGER.info(\"PermitKeepAliveTimeMinutes:\" + chaincodeServerProperties.getPermitKeepAliveTimeMinutes());\n            LOGGER.info(\"KeepAliveTimeMinutes:\" + chaincodeServerProperties.getKeepAliveTimeMinutes());\n            LOGGER.info(\"PermitKeepAliveWithoutCalls:\" + chaincodeServerProperties.getPermitKeepAliveWithoutCalls());\n            LOGGER.info(\"KeyPassword:\" + chaincodeServerProperties.getKeyPassword());\n            LOGGER.info(\"KeyCertChainFile:\" + chaincodeServerProperties.getKeyCertChainFile());\n            LOGGER.info(\"KeyFile:\" + chaincodeServerProperties.getKeyFile());\n            LOGGER.info(\"isTlsEnabled:\" + chaincodeServerProperties.isTlsEnabled());\n            LOGGER.info(\"\\n\");\n        }\n\n        this.server = serverBuilder.build();\n    }\n\n    private static void configureTls(\n            final NettyServerBuilder serverBuilder, final ChaincodeServerProperties chaincodeServerProperties)\n            throws SSLException {\n        final File keyCertChainFile =\n                Paths.get(chaincodeServerProperties.getKeyCertChainFile()).toFile();\n        final File keyFile = Paths.get(chaincodeServerProperties.getKeyFile()).toFile();\n\n        final SslContextBuilder sslContextBuilder;\n        if (chaincodeServerProperties.getKeyPassword() == null\n                || chaincodeServerProperties.getKeyPassword().isEmpty()) {\n            sslContextBuilder = SslContextBuilder.forServer(keyCertChainFile, keyFile);\n        } else {\n            sslContextBuilder =\n                    SslContextBuilder.forServer(keyCertChainFile, keyFile, chaincodeServerProperties.getKeyPassword());\n        }\n\n        ApplicationProtocolConfig apn = new ApplicationProtocolConfig(\n                ApplicationProtocolConfig.Protocol.ALPN,\n                ApplicationProtocolConfig.SelectorFailureBehavior.NO_ADVERTISE,\n                ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT,\n                ApplicationProtocolNames.HTTP_2);\n        sslContextBuilder.applicationProtocolConfig(apn);\n\n        if (chaincodeServerProperties.getTrustCertCollectionFile() != null) {\n            final File trustCertCollectionFile = Paths.get(chaincodeServerProperties.getTrustCertCollectionFile())\n                    .toFile();\n            sslContextBuilder.clientAuth(ClientAuth.REQUIRE);\n            sslContextBuilder.trustManager(trustCertCollectionFile);\n        }\n\n        serverBuilder.sslContext(sslContextBuilder.build());\n    }\n\n    /**\n     * start grpc server.\n     *\n     * @throws IOException\n     */\n    @SuppressWarnings(\"PMD.SystemPrintln\")\n    @Override\n    public void start() throws IOException {\n        LOGGER.info(\"start grpc server\");\n        Runtime.getRuntime().addShutdownHook(new Thread(() -> {\n            // Use stderr here since the logger may have been reset by its JVM shutdown hook.\n            System.err.println(\"*** shutting down gRPC server since JVM is shutting down\");\n            stop();\n            System.err.println(\"*** server shut down\");\n        }));\n        server.start();\n    }\n\n    /**\n     * Waits for the server to become terminated.\n     *\n     * @throws InterruptedException\n     */\n    @Override\n    public void blockUntilShutdown() throws InterruptedException {\n        LOGGER.info(\"Waits for the server to become terminated.\");\n        server.awaitTermination();\n    }\n\n    /** shutdown now grpc server. */\n    @Override\n    public void stop() {\n        LOGGER.info(\"shutdown now grpc server.\");\n        server.shutdownNow();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ResponseUtils.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim;\n\nimport static org.hyperledger.fabric.shim.Chaincode.Response.Status.INTERNAL_SERVER_ERROR;\nimport static org.hyperledger.fabric.shim.Chaincode.Response.Status.SUCCESS;\n\nimport org.hyperledger.fabric.Logger;\n\npublic final class ResponseUtils {\n\n    private static Logger logger = Logger.getLogger(ResponseUtils.class.getName());\n\n    private ResponseUtils() {}\n\n    /**\n     * @param message\n     * @param payload\n     * @return Chaincode.Response\n     */\n    public static Chaincode.Response newSuccessResponse(final String message, final byte[] payload) {\n        return new Chaincode.Response(SUCCESS, message, payload);\n    }\n\n    /** @return Chaincode.Response */\n    public static Chaincode.Response newSuccessResponse() {\n        return newSuccessResponse(null, null);\n    }\n\n    /**\n     * @param message\n     * @return Chaincode.Response\n     */\n    public static Chaincode.Response newSuccessResponse(final String message) {\n        return newSuccessResponse(message, null);\n    }\n\n    /**\n     * @param payload\n     * @return Chaincode.Response\n     */\n    public static Chaincode.Response newSuccessResponse(final byte[] payload) {\n        return newSuccessResponse(null, payload);\n    }\n\n    /**\n     * @param message\n     * @param payload\n     * @return Chaincode.Response\n     */\n    public static Chaincode.Response newErrorResponse(final String message, final byte[] payload) {\n        return new Chaincode.Response(INTERNAL_SERVER_ERROR, message, payload);\n    }\n\n    /** @return Chaincode.Response */\n    public static Chaincode.Response newErrorResponse() {\n        return newErrorResponse(null, null);\n    }\n\n    /**\n     * @param message\n     * @return Chaincode.Response\n     */\n    public static Chaincode.Response newErrorResponse(final String message) {\n        return newErrorResponse(message, null);\n    }\n\n    /**\n     * @param payload\n     * @return Chaincode.Response\n     */\n    public static Chaincode.Response newErrorResponse(final byte[] payload) {\n        return newErrorResponse(null, payload);\n    }\n\n    /**\n     * @param throwable\n     * @return Chaincode.Response\n     */\n    public static Chaincode.Response newErrorResponse(final Throwable throwable) {\n        // Responses should not include internals like stack trace but make sure it gets\n        // logged\n        logger.error(() -> logger.formatError(throwable));\n\n        if (throwable instanceof ChaincodeException) {\n            String message = throwable.getMessage();\n            byte[] payload = ((ChaincodeException) throwable).getPayload();\n            return new Chaincode.Response(INTERNAL_SERVER_ERROR, message, payload);\n        }\n\n        return newErrorResponse(\"Unexpected error\", null);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ext/sbe/StateBasedEndorsement.java",
    "content": "/*\n * Copyright 2019 IBM DTCC All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.ext.sbe;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * StateBasedEndorsement provides a set of convenience methods to create and modify a state-based endorsement policy.\n * Endorsement policies created by this convenience layer will always be a logical AND of \"ORG.peer\" principals for one\n * or more ORGs specified by the caller.\n */\npublic interface StateBasedEndorsement {\n    /**\n     * Get the endorsement policy as bytes.\n     *\n     * @return the endorsement policy as bytes\n     */\n    byte[] policy();\n\n    /**\n     * Adds the specified orgs to the list of orgs that are required to endorse. All orgs MSP role types will be set to\n     * the role that is specified in the first parameter. Among other aspects the desired role depends on the channel's\n     * configuration: if it supports node OUs, it is likely going to be the PEER role, while the MEMBER role is the\n     * suited one if it does not.\n     *\n     * @param roleType the MSP role type\n     * @param organizations the list of organizations\n     */\n    void addOrgs(RoleType roleType, String... organizations);\n\n    /**\n     * deletes the specified channel orgs from the existing key-level endorsement policy for this KVS key.\n     *\n     * @param organizations the list of organizations\n     */\n    void delOrgs(String... organizations);\n\n    /**\n     * Returns an array of channel orgs that are required to endorse changes.\n     *\n     * @return List of organizations\n     */\n    List<String> listOrgs();\n\n    /** RoleType of an endorsement policy's identity. */\n    @SuppressWarnings(\"PMD.FieldNamingConventions\")\n    enum RoleType {\n        /** RoleTypeMember identifies an org's member identity. */\n        RoleTypeMember(\"MEMBER\"),\n        /** RoleTypePeer identifies an org's peer identity. */\n        RoleTypePeer(\"PEER\");\n\n        private static final Map<String, RoleType> reverseLookup = new HashMap<>();\n\n        static {\n            for (final RoleType item : values()) {\n                reverseLookup.put(item.getVal(), item);\n            }\n        }\n\n        private final String val;\n\n        RoleType(final String val) {\n            this.val = val;\n        }\n\n        /** @return String value */\n        public String getVal() {\n            return val;\n        }\n\n        /**\n         * @param val\n         * @return RoleType\n         */\n        public static RoleType forVal(final String val) {\n            if (!reverseLookup.containsKey(val)) {\n                throw new IllegalArgumentException(\"role type \" + val + \" does not exist\");\n            }\n            return reverseLookup.get(val);\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ext/sbe/impl/StateBasedEndorsementFactory.java",
    "content": "/*\n * Copyright 2019 IBM DTCC All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.ext.sbe.impl;\n\nimport org.hyperledger.fabric.shim.ext.sbe.StateBasedEndorsement;\n\n/** Factory for {@link StateBasedEndorsement} objects. */\npublic class StateBasedEndorsementFactory {\n    private static final StateBasedEndorsementFactory INSTANCE = new StateBasedEndorsementFactory();\n\n    /** @return Endorsement Factory */\n    public static StateBasedEndorsementFactory getInstance() {\n        return INSTANCE;\n    }\n\n    /**\n     * Constructs a state-based endorsement policy from a given serialized EP byte array. If the byte array is empty, a\n     * new EP is created.\n     *\n     * @param ep serialized endorsement policy\n     * @return New StateBasedEndorsement instance\n     */\n    public StateBasedEndorsement newStateBasedEndorsement(final byte[] ep) {\n        return new StateBasedEndorsementImpl(ep);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ext/sbe/impl/StateBasedEndorsementImpl.java",
    "content": "/*\n * Copyright 2019 IBM DTCC All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.ext.sbe.impl;\n\nimport com.google.protobuf.InvalidProtocolBufferException;\nimport java.util.ArrayList;\nimport java.util.Comparator;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\nimport org.hyperledger.fabric.protos.common.MSPPrincipal;\nimport org.hyperledger.fabric.protos.common.MSPPrincipal.Classification;\nimport org.hyperledger.fabric.protos.common.MSPRole;\nimport org.hyperledger.fabric.protos.common.MSPRole.MSPRoleType;\nimport org.hyperledger.fabric.protos.common.SignaturePolicy;\nimport org.hyperledger.fabric.protos.common.SignaturePolicyEnvelope;\nimport org.hyperledger.fabric.shim.ext.sbe.StateBasedEndorsement;\n\n/** Implements {@link StateBasedEndorsement}. */\npublic final class StateBasedEndorsementImpl implements StateBasedEndorsement {\n    @SuppressWarnings(\"PMD.ProperLogger\") // PMD 7.12.0 reports a false positive\n    private static final Log LOGGER = LogFactory.getLog(StateBasedEndorsementImpl.class);\n\n    private final Map<String, MSPRoleType> orgs = new HashMap<>();\n\n    StateBasedEndorsementImpl(final byte[] ep) {\n        byte[] sbe;\n        if (ep == null) {\n            sbe = new byte[] {};\n        } else {\n            sbe = ep;\n        }\n        try {\n            final SignaturePolicyEnvelope spe = SignaturePolicyEnvelope.parseFrom(sbe);\n            setMSPIDsFromSP(spe);\n        } catch (final InvalidProtocolBufferException e) {\n            throw new IllegalArgumentException(\"error unmarshalling endorsement policy bytes\", e);\n        }\n    }\n\n    @Override\n    public byte[] policy() {\n        final SignaturePolicyEnvelope spe = policyFromMSPIDs();\n        return spe.toByteArray();\n    }\n\n    @Override\n    public void addOrgs(final RoleType role, final String... organizations) {\n        MSPRoleType mspRole;\n        if (RoleType.RoleTypeMember == role) {\n            mspRole = MSPRoleType.MEMBER;\n        } else {\n            mspRole = MSPRoleType.PEER;\n        }\n        for (final String neworg : organizations) {\n            orgs.put(neworg, mspRole);\n        }\n    }\n\n    @Override\n    public void delOrgs(final String... organizations) {\n        for (final String delorg : organizations) {\n            orgs.remove(delorg);\n        }\n    }\n\n    @Override\n    public List<String> listOrgs() {\n        final List<String> res = new ArrayList<>();\n        res.addAll(orgs.keySet());\n        return res;\n    }\n\n    private void setMSPIDsFromSP(final SignaturePolicyEnvelope spe) {\n        spe.getIdentitiesList().stream()\n                .filter(identity -> Classification.ROLE == identity.getPrincipalClassification())\n                .forEach(this::addOrg);\n    }\n\n    private void addOrg(final MSPPrincipal identity) {\n        try {\n            final MSPRole mspRole = MSPRole.parseFrom(identity.getPrincipal());\n            orgs.put(mspRole.getMspIdentifier(), mspRole.getRole());\n        } catch (final InvalidProtocolBufferException e) {\n            LOGGER.warn(\"error unmarshalling msp principal\");\n            throw new IllegalArgumentException(\"error unmarshalling msp principal\", e);\n        }\n    }\n\n    private SignaturePolicyEnvelope policyFromMSPIDs() {\n        final List<String> mspids = listOrgs();\n\n        mspids.sort(Comparator.naturalOrder());\n        final List<MSPPrincipal> principals = new ArrayList<>();\n        final List<SignaturePolicy> sigpolicy = new ArrayList<>();\n        for (int i = 0; i < mspids.size(); i++) {\n            final String mspid = mspids.get(i);\n            principals.add(MSPPrincipal.newBuilder()\n                    .setPrincipalClassification(Classification.ROLE)\n                    .setPrincipal(MSPRole.newBuilder()\n                            .setMspIdentifier(mspid)\n                            .setRole(orgs.get(mspid))\n                            .build()\n                            .toByteString())\n                    .build());\n\n            sigpolicy.add(StateBasedEndorsementUtils.signedBy(i));\n        }\n\n        // create the policy: it requires exactly 1 signature from all of the principals\n        return SignaturePolicyEnvelope.newBuilder()\n                .setVersion(0)\n                .setRule(StateBasedEndorsementUtils.nOutOf(mspids.size(), sigpolicy))\n                .addAllIdentities(principals)\n                .build();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ext/sbe/impl/StateBasedEndorsementUtils.java",
    "content": "/*\n * Copyright 2019 IBM DTCC All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.ext.sbe.impl;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport org.hyperledger.fabric.protos.common.MSPPrincipal;\nimport org.hyperledger.fabric.protos.common.MSPPrincipal.Classification;\nimport org.hyperledger.fabric.protos.common.MSPRole;\nimport org.hyperledger.fabric.protos.common.MSPRole.MSPRoleType;\nimport org.hyperledger.fabric.protos.common.SignaturePolicy;\nimport org.hyperledger.fabric.protos.common.SignaturePolicy.NOutOf;\nimport org.hyperledger.fabric.protos.common.SignaturePolicyEnvelope;\n\n/** Utility to create {@link SignaturePolicy} and {@link SignaturePolicyEnvelope}. */\npublic final class StateBasedEndorsementUtils {\n\n    private StateBasedEndorsementUtils() {}\n\n    /**\n     * Creates a SignaturePolicy requiring a given signer's signature.\n     *\n     * @param index\n     * @return SignaturePolicy\n     */\n    static SignaturePolicy signedBy(final int index) {\n        return SignaturePolicy.newBuilder().setSignedBy(index).build();\n    }\n\n    /**\n     * Create a policy.\n     *\n     * <p>Creates a policy which requires N out of the slice of policies to evaluate to true\n     *\n     * @param n\n     * @param policies\n     * @return SignaturePolicy\n     */\n    static SignaturePolicy nOutOf(final int n, final List<SignaturePolicy> policies) {\n        return SignaturePolicy.newBuilder()\n                .setNOutOf(NOutOf.newBuilder().setN(n).addAllRules(policies).build())\n                .build();\n    }\n\n    /**\n     * Creates a {@link SignaturePolicyEnvelope} requiring 1 signature from any fabric entity, having the passed role,\n     * of the specified MSP.\n     *\n     * @param mspId\n     * @param role\n     * @return SignaturePolicy\n     */\n    static SignaturePolicyEnvelope signedByFabricEntity(final String mspId, final MSPRoleType role) {\n        // specify the principal: it's a member of the msp we just found\n        final MSPPrincipal principal = MSPPrincipal.newBuilder()\n                .setPrincipalClassification(Classification.ROLE)\n                .setPrincipal(MSPRole.newBuilder()\n                        .setMspIdentifier(mspId)\n                        .setRole(role)\n                        .build()\n                        .toByteString())\n                .build();\n\n        // create the policy: it requires exactly 1 signature from the first (and only)\n        // principal\n        return SignaturePolicyEnvelope.newBuilder()\n                .setVersion(0)\n                .setRule(nOutOf(1, Arrays.asList(signedBy(0))))\n                .addIdentities(principal)\n                .build();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ext/sbe/impl/package-info.java",
    "content": "/*\n * Copyright 2023 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.ext.sbe.impl;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ext/sbe/package-info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/** Provides an interface for creating and modifying state-based endorsement policies. */\npackage org.hyperledger.fabric.shim.ext.sbe;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/impl/ChaincodeInvocationTask.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.impl;\n\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.COMPLETED;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.ERROR;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.RESPONSE;\n\nimport com.google.protobuf.ByteString;\nimport com.google.protobuf.InvalidProtocolBufferException;\nimport io.opentelemetry.api.trace.Span;\nimport io.opentelemetry.api.trace.StatusCode;\nimport java.security.NoSuchAlgorithmException;\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.Callable;\nimport java.util.function.Consumer;\nimport java.util.logging.Logger;\nimport org.hyperledger.fabric.Logging;\nimport org.hyperledger.fabric.contract.ContractRuntimeException;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type;\nimport org.hyperledger.fabric.shim.Chaincode;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.hyperledger.fabric.traces.Traces;\n\n/** A 'Callable' implementation the has the job of invoking the chaincode, and matching the response and requests. */\n@SuppressWarnings(\"PMD.MoreThanOneLogger\")\npublic class ChaincodeInvocationTask implements Callable<ChaincodeMessage> {\n\n    private static final Logger LOGGER = Logger.getLogger(ChaincodeInvocationTask.class.getName());\n    private static final Logger PERFLOGGER = Logger.getLogger(Logging.PERFLOGGER);\n\n    private final String key;\n    private final Type type;\n    private final String txId;\n    private final Consumer<ChaincodeMessage> outgoingMessageConsumer;\n    // default to size 2: Based on the protocol there *should* only ever be one thing within this\n    // ArrayBlockingQueue provides the correct semantics out-of-the-box.\n    // We want consumers to be block waiting on a message to be 'posted' but for the putter to not be held\n    // up if there's no body waiting.\n    //\n    // Usual case should be the main thread is waiting for something to come back\n    private final BlockingQueue<ChaincodeMessage> postbox = new ArrayBlockingQueue<>(2, true);\n\n    private final ChaincodeMessage message;\n    private final Chaincode chaincode;\n\n    /**\n     * @param message The incoming message that has triggered this task into execution\n     * @param type Is this init or invoke? (v2 Fabric deprecates init)\n     * @param outgoingMessage The Consumer functional interface to send any requests for ledger state\n     * @param chaincode A instance of the end users chaincode\n     */\n    public ChaincodeInvocationTask(\n            final ChaincodeMessage message,\n            final Type type,\n            final Consumer<ChaincodeMessage> outgoingMessage,\n            final Chaincode chaincode) {\n\n        this.key = message.getChannelId() + message.getTxid();\n        this.type = type;\n        this.outgoingMessageConsumer = outgoingMessage;\n        this.txId = message.getTxid();\n        this.chaincode = chaincode;\n        this.message = message;\n    }\n\n    /** Main method to power the invocation of the chaincode. */\n    @Override\n    @SuppressWarnings(\"PMD.AvoidCatchingGenericException\")\n    public ChaincodeMessage call() {\n        ChaincodeMessage finalResponseMessage;\n\n        Span span = null;\n        try {\n            try {\n                PERFLOGGER.fine(() -> \"> task:start TX::\" + this.txId);\n\n                // A key interface for the chaincode's invoke() method implementation\n                // is the 'ChaincodeStub' interface. An instance of this is created\n                // per transaction invocation.\n                //\n                // This needs to be passed the message triggering the invoke, as well\n                // as the interface to be used for sending any requests to the peer\n                final ChaincodeStub stub = new InvocationStubImpl(message, this);\n\n                span = Traces.getProvider().createSpan(stub);\n                // result is what will be sent to the peer as a response to this invocation\n                final Chaincode.Response result;\n\n                PERFLOGGER.fine(() -> \"> task:invoke TX::\" + this.txId);\n\n                // Call chaincode's invoke\n                // Note in Fabric v2, there won't be any INIT\n                if (this.type == Type.INIT) {\n                    result = chaincode.init(stub);\n                } else {\n                    result = chaincode.invoke(stub);\n                }\n\n                PERFLOGGER.fine(() -> \"< task:invoke TX::\" + this.txId);\n\n                if (result.getStatus().getCode() >= Chaincode.Response.Status.INTERNAL_SERVER_ERROR.getCode()) {\n                    // Send ERROR with entire result.Message as payload\n                    LOGGER.severe(() -> String.format(\n                            \"[%-8.8s] Invoke failed with error code %d. Sending %s\",\n                            message.getTxid(), result.getStatus().getCode(), ERROR));\n                    finalResponseMessage = ChaincodeMessageFactory.newCompletedEventMessage(\n                            message.getChannelId(), message.getTxid(), result, stub.getEvent());\n                    if (span != null) {\n                        span.setStatus(StatusCode.ERROR, result.getMessage());\n                    }\n                } else {\n                    // Send COMPLETED with entire result as payload\n                    LOGGER.fine(\n                            () -> String.format(\"[%-8.8s] Invoke succeeded. Sending %s\", message.getTxid(), COMPLETED));\n                    finalResponseMessage = ChaincodeMessageFactory.newCompletedEventMessage(\n                            message.getChannelId(), message.getTxid(), result, stub.getEvent());\n                }\n\n            } catch (InvalidProtocolBufferException | NoSuchAlgorithmException | RuntimeException e) {\n                LOGGER.severe(\n                        () -> String.format(\"[%-8.8s] Invoke failed. Sending %s: %s\", message.getTxid(), ERROR, e));\n                finalResponseMessage =\n                        ChaincodeMessageFactory.newErrorEventMessage(message.getChannelId(), message.getTxid(), e);\n                if (span != null) {\n                    span.setStatus(StatusCode.ERROR, e.getMessage());\n                }\n            }\n\n            // send the final response message to the peer\n            outgoingMessageConsumer.accept(finalResponseMessage);\n            PERFLOGGER.fine(() -> \"< task:end TX::\" + this.txId);\n        } finally {\n            if (span != null) {\n                span.end();\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * Identifier of this task, channel id and transaction id.\n     *\n     * @return String\n     */\n    public String getTxKey() {\n        return this.key;\n    }\n\n    /**\n     * Use the Key as to determine equality.\n     *\n     * @param other\n     * @return equality\n     */\n    @Override\n    public boolean equals(final Object other) {\n        if (!(other instanceof ChaincodeInvocationTask)) {\n            return false;\n        }\n\n        ChaincodeInvocationTask that = (ChaincodeInvocationTask) other;\n        return this.key.equals(that.getTxKey());\n    }\n\n    @Override\n    public int hashCode() {\n        return key.hashCode();\n    }\n\n    /**\n     * Posts the message that the peer has responded with to this task's request Uses an 'ArrayBlockingQueue'. This lets\n     * the producer post messages without waiting for the consumer. And the consumer can block until a message is\n     * posted.\n     *\n     * <p>In this case the data is only passed to the executing tasks.\n     *\n     * @param msg Chaincode message to pass pack\n     * @throws InterruptedException should something really really go wrong\n     */\n    public void postMessage(final ChaincodeMessage msg) throws InterruptedException {\n        // put to the postbox waiting for space to become available if needed\n        postbox.put(msg);\n    }\n\n    /**\n     * Send the chaincode message back to the peer.\n     *\n     * <p>Implementation of the Functional interface 'InvokeChaincodeSupport'\n     *\n     * <p>It will send the message, via the outgoingMessageConsumer, and then block on the 'Exchanger' to wait for the\n     * response to come.\n     *\n     * <p>This Exchange is an atomic operation between the thread that is running this task, and the thread that is\n     * handling the communication from the peer.\n     *\n     * @param message The chaincode message from the peer\n     * @return ByteString to be parsed by the caller\n     */\n    protected ByteString invoke(final ChaincodeMessage message) {\n\n        // send the message\n        LOGGER.fine(() -> \"Task Sending message to the peer \" + message.getTxid());\n        outgoingMessageConsumer.accept(message);\n\n        // wait for response\n        ChaincodeMessage response;\n        try {\n            PERFLOGGER.fine(() -> \"> task:answer TX::\" + message.getTxid());\n            response = postbox.take();\n            PERFLOGGER.fine(() -> \"< task:answer TX::\" + message.getTxid());\n        } catch (final InterruptedException e) {\n            LOGGER.severe(() -> \"Interrupted exchanging messages \");\n            throw new ContractRuntimeException(String.format(\"[%-8.8s]InterruptedException received.\", txId), e);\n        }\n\n        // handle response\n        switch (response.getType()) {\n            case RESPONSE:\n                LOGGER.fine(() -> String.format(\"[%-8.8s] Successful response received.\", txId));\n                return response.getPayload();\n            case ERROR:\n                LOGGER.severe(() -> String.format(\"[%-8.8s] Unsuccessful response received.\", txId));\n                throw new ContractRuntimeException(String.format(\"[%-8.8s]Unsuccessful response received.\", txId));\n            default:\n                LOGGER.severe(() -> String.format(\n                        \"[%-8.8s] Unexpected %s response received. Expected %s or %s.\",\n                        txId, response.getType(), RESPONSE, ERROR));\n                throw new IllegalStateException(String.format(\n                        \"[%-8.8s] Unexpected %s response received. Expected %s or %s.\",\n                        txId, response.getType(), RESPONSE, ERROR));\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/impl/ChaincodeMessageFactory.java",
    "content": "/*\n * Copyright 2019 IBM DTCC All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.impl;\n\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.COMPLETED;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.DEL_STATE;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.ERROR;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.GET_PRIVATE_DATA_HASH;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.GET_STATE;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.GET_STATE_METADATA;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.INVOKE_CHAINCODE;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.PUT_STATE;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.PUT_STATE_METADATA;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.REGISTER;\n\nimport com.google.protobuf.ByteString;\nimport java.io.PrintWriter;\nimport java.io.StringWriter;\nimport org.hyperledger.fabric.protos.peer.ChaincodeEvent;\nimport org.hyperledger.fabric.protos.peer.ChaincodeID;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type;\nimport org.hyperledger.fabric.protos.peer.DelState;\nimport org.hyperledger.fabric.protos.peer.GetState;\nimport org.hyperledger.fabric.protos.peer.GetStateMetadata;\nimport org.hyperledger.fabric.protos.peer.PutState;\nimport org.hyperledger.fabric.protos.peer.PutStateMetadata;\nimport org.hyperledger.fabric.protos.peer.Response;\nimport org.hyperledger.fabric.protos.peer.Response.Builder;\nimport org.hyperledger.fabric.protos.peer.StateMetadata;\nimport org.hyperledger.fabric.shim.Chaincode;\n\npublic final class ChaincodeMessageFactory {\n\n    private ChaincodeMessageFactory() {}\n\n    static ChaincodeMessage newGetPrivateDataHashEventMessage(\n            final String channelId, final String txId, final String collection, final String key) {\n        return newEventMessage(\n                GET_PRIVATE_DATA_HASH,\n                channelId,\n                txId,\n                GetState.newBuilder()\n                        .setCollection(collection)\n                        .setKey(key)\n                        .build()\n                        .toByteString());\n    }\n\n    static ChaincodeMessage newGetStateEventMessage(\n            final String channelId, final String txId, final String collection, final String key) {\n        return newEventMessage(\n                GET_STATE,\n                channelId,\n                txId,\n                GetState.newBuilder()\n                        .setCollection(collection)\n                        .setKey(key)\n                        .build()\n                        .toByteString());\n    }\n\n    static ChaincodeMessage newGetStateMetadataEventMessage(\n            final String channelId, final String txId, final String collection, final String key) {\n        return newEventMessage(\n                GET_STATE_METADATA,\n                channelId,\n                txId,\n                GetStateMetadata.newBuilder()\n                        .setCollection(collection)\n                        .setKey(key)\n                        .build()\n                        .toByteString());\n    }\n\n    static ChaincodeMessage newPutStateEventMessage(\n            final String channelId,\n            final String txId,\n            final String collection,\n            final String key,\n            final ByteString value) {\n        return newEventMessage(\n                PUT_STATE,\n                channelId,\n                txId,\n                PutState.newBuilder()\n                        .setCollection(collection)\n                        .setKey(key)\n                        .setValue(value)\n                        .build()\n                        .toByteString());\n    }\n\n    static ChaincodeMessage newPutStateMetadataEventMessage(\n            final String channelId,\n            final String txId,\n            final String collection,\n            final String key,\n            final String metakey,\n            final ByteString value) {\n        return newEventMessage(\n                PUT_STATE_METADATA,\n                channelId,\n                txId,\n                PutStateMetadata.newBuilder()\n                        .setCollection(collection)\n                        .setKey(key)\n                        .setMetadata(StateMetadata.newBuilder()\n                                .setMetakey(metakey)\n                                .setValue(value)\n                                .build())\n                        .build()\n                        .toByteString());\n    }\n\n    static ChaincodeMessage newDeleteStateEventMessage(\n            final String channelId, final String txId, final String collection, final String key) {\n        return newEventMessage(\n                DEL_STATE,\n                channelId,\n                txId,\n                DelState.newBuilder()\n                        .setCollection(collection)\n                        .setKey(key)\n                        .build()\n                        .toByteString());\n    }\n\n    static ChaincodeMessage newPurgeStateEventMessage(\n            final String channelId, final String txId, final String collection, final String key) {\n        return newEventMessage(\n                Type.PURGE_PRIVATE_DATA,\n                channelId,\n                txId,\n                DelState.newBuilder()\n                        .setCollection(collection)\n                        .setKey(key)\n                        .build()\n                        .toByteString());\n    }\n\n    static ChaincodeMessage newErrorEventMessage(final String channelId, final String txId, final Throwable throwable) {\n        return newErrorEventMessage(channelId, txId, printStackTrace(throwable));\n    }\n\n    static ChaincodeMessage newErrorEventMessage(final String channelId, final String txId, final String message) {\n        return newErrorEventMessage(channelId, txId, message, null);\n    }\n\n    static ChaincodeMessage newErrorEventMessage(\n            final String channelId, final String txId, final String message, final ChaincodeEvent event) {\n        return newEventMessage(ERROR, channelId, txId, ByteString.copyFromUtf8(message), event);\n    }\n\n    static ChaincodeMessage newCompletedEventMessage(\n            final String channelId, final String txId, final Chaincode.Response response, final ChaincodeEvent event) {\n        return newEventMessage(\n                COMPLETED, channelId, txId, toProtoResponse(response).toByteString(), event);\n    }\n\n    static ChaincodeMessage newInvokeChaincodeMessage(\n            final String channelId, final String txId, final ByteString payload) {\n        return newEventMessage(INVOKE_CHAINCODE, channelId, txId, payload, null);\n    }\n\n    static ChaincodeMessage newRegisterChaincodeMessage(final ChaincodeID chaincodeId) {\n        return ChaincodeMessage.newBuilder()\n                .setType(REGISTER)\n                .setPayload(chaincodeId.toByteString())\n                .build();\n    }\n\n    static ChaincodeMessage newEventMessage(\n            final Type type, final String channelId, final String txId, final ByteString payload) {\n        return newEventMessage(type, channelId, txId, payload, null);\n    }\n\n    static ChaincodeMessage newEventMessage(\n            final Type type,\n            final String channelId,\n            final String txId,\n            final ByteString payload,\n            final ChaincodeEvent event) {\n        final ChaincodeMessage.Builder builder = ChaincodeMessage.newBuilder()\n                .setType(type)\n                .setChannelId(channelId)\n                .setTxid(txId)\n                .setPayload(payload);\n        if (event != null) {\n            builder.setChaincodeEvent(event);\n        }\n        return builder.build();\n    }\n\n    private static Response toProtoResponse(final Chaincode.Response response) {\n        final Builder builder = Response.newBuilder();\n        builder.setStatus(response.getStatus().getCode());\n        if (response.getMessage() != null) {\n            builder.setMessage(response.getMessage());\n        }\n        if (response.getPayload() != null) {\n            builder.setPayload(ByteString.copyFrom(response.getPayload()));\n        }\n        return builder.build();\n    }\n\n    private static String printStackTrace(final Throwable throwable) {\n        if (throwable == null) {\n            return null;\n        }\n        final StringWriter buffer = new StringWriter();\n        throwable.printStackTrace(new PrintWriter(buffer));\n        return buffer.toString();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/impl/ChaincodeSupportClient.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.impl;\n\nimport io.grpc.ClientInterceptor;\nimport io.grpc.ManagedChannel;\nimport io.grpc.ManagedChannelBuilder;\nimport io.grpc.stub.StreamObserver;\nimport java.io.IOException;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.function.Consumer;\nimport java.util.logging.Logger;\nimport org.hyperledger.fabric.Logging;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.ChaincodeSupportGrpc;\nimport org.hyperledger.fabric.protos.peer.ChaincodeSupportGrpc.ChaincodeSupportStub;\nimport org.hyperledger.fabric.traces.Traces;\n\npublic class ChaincodeSupportClient {\n    private static final int DEFAULT_TIMEOUT = 5;\n    private static final Logger PERFLOGGER = Logger.getLogger(Logging.PERFLOGGER);\n    private final ManagedChannel channel;\n    private final ChaincodeSupportStub stub;\n\n    /** @param channelBuilder */\n    public ChaincodeSupportClient(final ManagedChannelBuilder<?> channelBuilder) {\n        ClientInterceptor interceptor = Traces.getProvider().createInterceptor();\n        if (interceptor != null) {\n            channelBuilder.intercept(interceptor);\n        }\n        this.channel = channelBuilder.build();\n        this.stub = ChaincodeSupportGrpc.newStub(channel);\n    }\n\n    /** @param itm */\n    public void shutdown(final InvocationTaskManager itm) {\n\n        // first shutdown the thread pool\n        itm.shutdown();\n        try {\n            this.channel.shutdown();\n            if (!channel.awaitTermination(DEFAULT_TIMEOUT, TimeUnit.SECONDS)) {\n                channel.shutdownNow();\n            }\n\n        } catch (final InterruptedException e) {\n            channel.shutdownNow();\n            Thread.currentThread().interrupt();\n        }\n    }\n\n    /**\n     * @param itm\n     * @param requestObserver\n     * @throws IOException verify parameters error\n     */\n    public void start(final InvocationTaskManager itm, final StreamObserver<ChaincodeMessage> requestObserver)\n            throws IOException {\n        if (requestObserver == null) {\n            throw new IOException(\"StreamObserver 'requestObserver' for chat with peer can't be null\");\n        }\n        if (itm == null) {\n            throw new IOException(\"InnvocationTaskManager 'itm' can't be null\");\n        }\n\n        // Consumer function for response messages (those going back to the peer)\n        // gRPC streams need to be accessed by one thread at a time, so\n        // use a lock to protect this.\n        //\n        // Previous implementations used a dedicated thread for this. However this extra\n        // thread is not really required. The main thread executing the transaction will\n        // not be\n        // held up for long, nor can any one transaction invoke more that one stub api\n        // at a time.\n        // create a lock, with fair property\n        final ReentrantLock lock = new ReentrantLock(true);\n        final Consumer<ChaincodeMessage> consumer = t -> {\n            lock.lock();\n            PERFLOGGER.fine(() -> \"> sendToPeer TX::\" + t.getTxid());\n            requestObserver.onNext(t);\n            PERFLOGGER.fine(() -> \"< sendToPeer TX::\" + t.getTxid());\n            lock.unlock();\n        };\n\n        // Pass a Consumer interface back to the the task manager. This is for tasks to\n        // use to respond back to the peer.\n        //\n        // NOTE the register() - very important - as this triggers the ITM to send the\n        // first message to the peer; otherwise the both sides will sit there waiting\n        itm.setResponseConsumer(consumer);\n        itm.register();\n    }\n\n    /**\n     * ChaincodeSupportStub.\n     *\n     * @return stub\n     */\n    public ChaincodeSupportStub getStub() {\n        return stub;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/impl/InvocationStubImpl.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.impl;\n\nimport static java.util.stream.Collectors.toList;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.COMPLETED;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.GET_HISTORY_FOR_KEY;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.GET_PRIVATE_DATA_HASH;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.GET_QUERY_RESULT;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.GET_STATE_BY_RANGE;\n\nimport com.google.protobuf.ByteString;\nimport com.google.protobuf.InvalidProtocolBufferException;\nimport com.google.protobuf.Timestamp;\nimport java.io.UncheckedIOException;\nimport java.nio.ByteBuffer;\nimport java.nio.ByteOrder;\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\nimport java.time.Instant;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.function.Function;\nimport java.util.logging.Logger;\nimport java.util.stream.Collectors;\nimport org.hyperledger.fabric.protos.common.ChannelHeader;\nimport org.hyperledger.fabric.protos.common.Header;\nimport org.hyperledger.fabric.protos.common.HeaderType;\nimport org.hyperledger.fabric.protos.common.SignatureHeader;\nimport org.hyperledger.fabric.protos.ledger.queryresult.KV;\nimport org.hyperledger.fabric.protos.peer.ChaincodeEvent;\nimport org.hyperledger.fabric.protos.peer.ChaincodeID;\nimport org.hyperledger.fabric.protos.peer.ChaincodeInput;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.ChaincodeProposalPayload;\nimport org.hyperledger.fabric.protos.peer.ChaincodeSpec;\nimport org.hyperledger.fabric.protos.peer.GetQueryResult;\nimport org.hyperledger.fabric.protos.peer.GetState;\nimport org.hyperledger.fabric.protos.peer.GetStateByRange;\nimport org.hyperledger.fabric.protos.peer.MetaDataKeys;\nimport org.hyperledger.fabric.protos.peer.Proposal;\nimport org.hyperledger.fabric.protos.peer.QueryMetadata;\nimport org.hyperledger.fabric.protos.peer.QueryResultBytes;\nimport org.hyperledger.fabric.protos.peer.Response;\nimport org.hyperledger.fabric.protos.peer.SignedProposal;\nimport org.hyperledger.fabric.protos.peer.StateMetadataResult;\nimport org.hyperledger.fabric.shim.Chaincode;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.hyperledger.fabric.shim.ledger.CompositeKey;\nimport org.hyperledger.fabric.shim.ledger.KeyModification;\nimport org.hyperledger.fabric.shim.ledger.KeyValue;\nimport org.hyperledger.fabric.shim.ledger.QueryResultsIterator;\nimport org.hyperledger.fabric.shim.ledger.QueryResultsIteratorWithMetadata;\n\n@SuppressWarnings({\"PMD.CyclomaticComplexity\", \"PMD.GodClass\"})\nclass InvocationStubImpl implements ChaincodeStub {\n\n    private static final String UNSPECIFIED_START_KEY = new String(Character.toChars(0x000001));\n    private static final String UNSPECIFIED_END_KEY = \"\";\n    private static final Logger LOGGER = Logger.getLogger(InvocationStubImpl.class.getName());\n\n    public static final String MAX_UNICODE_RUNE = \"\\udbff\\udfff\";\n    private static final String CORE_PEER_LOCALMSPID = \"CORE_PEER_LOCALMSPID\";\n\n    private static final Function<QueryResultBytes, org.hyperledger.fabric.protos.ledger.queryresult.KeyModification>\n            QUERY_RESULT_BYTES_TO_KEY_MODIFICATION = queryResultBytes -> {\n                try {\n                    return org.hyperledger.fabric.protos.ledger.queryresult.KeyModification.parseFrom(\n                            queryResultBytes.getResultBytes());\n                } catch (final InvalidProtocolBufferException e) {\n                    throw new UncheckedIOException(e);\n                }\n            };\n    private static final Function<QueryResultBytes, KV> QUERY_RESULT_BYTES_TO_KV = queryResultBytes -> {\n        try {\n            return KV.parseFrom(queryResultBytes.getResultBytes());\n        } catch (final InvalidProtocolBufferException e) {\n            throw new UncheckedIOException(e);\n        }\n    };\n\n    private final String channelId;\n    private final String txId;\n    private final ChaincodeInvocationTask handler;\n    private final List<ByteString> args;\n    private final SignedProposal signedProposal;\n    private final Instant txTimestamp;\n    private final ByteString creator;\n    private final Map<String, ByteString> transientMap;\n    private final byte[] binding;\n    private ChaincodeEvent event;\n\n    /**\n     * @param message\n     * @param handler\n     * @throws InvalidProtocolBufferException\n     */\n    InvocationStubImpl(final ChaincodeMessage message, final ChaincodeInvocationTask handler)\n            throws InvalidProtocolBufferException, NoSuchAlgorithmException {\n        this.channelId = message.getChannelId();\n        this.txId = message.getTxid();\n        this.handler = handler;\n        final ChaincodeInput input = ChaincodeInput.parseFrom(message.getPayload());\n\n        this.args = Collections.unmodifiableList(input.getArgsList());\n        this.signedProposal = message.getProposal();\n        if (this.signedProposal.getProposalBytes().isEmpty()) {\n            this.creator = null;\n            this.txTimestamp = null;\n            this.transientMap = Collections.emptyMap();\n            this.binding = null;\n        } else {\n            final Proposal proposal = Proposal.parseFrom(signedProposal.getProposalBytes());\n            final Header header = Header.parseFrom(proposal.getHeader());\n            final ChannelHeader channelHeader = ChannelHeader.parseFrom(header.getChannelHeader());\n            validateProposalType(channelHeader);\n            final SignatureHeader signatureHeader = SignatureHeader.parseFrom(header.getSignatureHeader());\n            final ChaincodeProposalPayload chaincodeProposalPayload =\n                    ChaincodeProposalPayload.parseFrom(proposal.getPayload());\n            final Timestamp timestamp = channelHeader.getTimestamp();\n\n            this.txTimestamp = Instant.ofEpochSecond(timestamp.getSeconds(), timestamp.getNanos());\n            this.creator = signatureHeader.getCreator();\n            this.transientMap = chaincodeProposalPayload.getTransientMapMap();\n            this.binding = computeBinding(channelHeader, signatureHeader);\n        }\n    }\n\n    private static boolean isEmptyString(final String str) {\n        for (int i = 0; i < str.length(); i++) {\n            if (!Character.isWhitespace(str.charAt(i))) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    private byte[] computeBinding(final ChannelHeader channelHeader, final SignatureHeader signatureHeader)\n            throws NoSuchAlgorithmException {\n        final MessageDigest messageDigest = MessageDigest.getInstance(\"SHA-256\");\n        messageDigest.update(signatureHeader.getNonce().asReadOnlyByteBuffer());\n        messageDigest.update(this.creator.asReadOnlyByteBuffer());\n        final ByteBuffer epochBytes =\n                ByteBuffer.allocate(Long.BYTES).order(ByteOrder.LITTLE_ENDIAN).putLong(channelHeader.getEpoch());\n        epochBytes.flip();\n        messageDigest.update(epochBytes);\n        return messageDigest.digest();\n    }\n\n    private void validateProposalType(final ChannelHeader channelHeader) {\n        switch (HeaderType.forNumber(channelHeader.getType())) {\n            case ENDORSER_TRANSACTION:\n            case CONFIG:\n                return;\n            default:\n                throw new IllegalArgumentException(String.format(\n                        \"Unexpected transaction type: %s\", HeaderType.forNumber(channelHeader.getType())));\n        }\n    }\n\n    @Override\n    public List<byte[]> getArgs() {\n        return args.stream().map(ByteString::toByteArray).collect(toList());\n    }\n\n    @Override\n    public List<String> getStringArgs() {\n        return args.stream().map(ByteString::toStringUtf8).collect(toList());\n    }\n\n    @Override\n    public String getFunction() {\n        return getStringArgs().isEmpty() ? null : getStringArgs().get(0);\n    }\n\n    @Override\n    public List<String> getParameters() {\n        return getStringArgs().stream().skip(1).collect(toList());\n    }\n\n    @Override\n    public void setEvent(final String name, final byte[] payload) {\n        if (null == name || isEmptyString(name)) {\n            throw new IllegalArgumentException(\"event name can not be nil string\");\n        }\n        if (payload != null) {\n            this.event = ChaincodeEvent.newBuilder()\n                    .setEventName(name)\n                    .setPayload(ByteString.copyFrom(payload))\n                    .build();\n        } else {\n            this.event = ChaincodeEvent.newBuilder().setEventName(name).build();\n        }\n    }\n\n    @Override\n    public ChaincodeEvent getEvent() {\n        return event;\n    }\n\n    @Override\n    public String getChannelId() {\n        return channelId;\n    }\n\n    @Override\n    public String getTxId() {\n        return txId;\n    }\n\n    @Override\n    public byte[] getState(final String key) {\n        return this.handler\n                .invoke(ChaincodeMessageFactory.newGetStateEventMessage(channelId, txId, \"\", key))\n                .toByteArray();\n    }\n\n    @Override\n    @SuppressWarnings(\"PMD.ReturnEmptyCollectionRatherThanNull\")\n    public byte[] getStateValidationParameter(final String key) {\n\n        final ByteString payload =\n                handler.invoke(ChaincodeMessageFactory.newGetStateMetadataEventMessage(channelId, txId, \"\", key));\n        try {\n            final StateMetadataResult stateMetadataResult = StateMetadataResult.parseFrom(payload);\n            final Map<String, ByteString> stateMetadataMap = new HashMap<>();\n            stateMetadataResult\n                    .getEntriesList()\n                    .forEach(entry -> stateMetadataMap.put(entry.getMetakey(), entry.getValue()));\n\n            if (stateMetadataMap.containsKey(MetaDataKeys.VALIDATION_PARAMETER.toString())) {\n                return stateMetadataMap\n                        .get(MetaDataKeys.VALIDATION_PARAMETER.toString())\n                        .toByteArray();\n            }\n        } catch (final InvalidProtocolBufferException e) {\n            LOGGER.severe(() -> String.format(\"[%-8.8s] unmarshalling error\", txId));\n            throw new UncheckedIOException(\"Error unmarshalling StateMetadataResult.\", e);\n        }\n\n        return null;\n    }\n\n    @Override\n    public void putState(final String key, final byte[] value) {\n        validateKey(key);\n        this.handler.invoke(\n                ChaincodeMessageFactory.newPutStateEventMessage(channelId, txId, \"\", key, ByteString.copyFrom(value)));\n    }\n\n    @Override\n    public void setStateValidationParameter(final String key, final byte[] value) {\n        validateKey(key);\n        final ChaincodeMessage msg = ChaincodeMessageFactory.newPutStateMetadataEventMessage(\n                channelId, txId, \"\", key, MetaDataKeys.VALIDATION_PARAMETER.toString(), ByteString.copyFrom(value));\n        this.handler.invoke(msg);\n    }\n\n    @Override\n    public void delState(final String key) {\n        final ChaincodeMessage msg = ChaincodeMessageFactory.newDeleteStateEventMessage(channelId, txId, \"\", key);\n        this.handler.invoke(msg);\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getStateByRange(final String startKey, final String endKey) {\n        String start = startKey;\n        String end = endKey;\n\n        if (startKey == null || startKey.isEmpty()) {\n            start = UNSPECIFIED_START_KEY;\n        }\n        if (endKey == null) {\n            end = UNSPECIFIED_END_KEY;\n        }\n        CompositeKey.validateSimpleKeys(start, end);\n\n        return executeGetStateByRange(\"\", start, end);\n    }\n\n    private QueryResultsIterator<KeyValue> executeGetStateByRange(\n            final String collection, final String startKey, final String endKey) {\n\n        final ByteString requestPayload = GetStateByRange.newBuilder()\n                .setCollection(collection)\n                .setStartKey(startKey)\n                .setEndKey(endKey)\n                .build()\n                .toByteString();\n\n        final ChaincodeMessage requestMessage =\n                ChaincodeMessageFactory.newEventMessage(GET_STATE_BY_RANGE, channelId, txId, requestPayload);\n        final ByteString response = handler.invoke(requestMessage);\n\n        return new QueryResultsIteratorImpl<>(\n                this.handler, channelId, txId, response, QUERY_RESULT_BYTES_TO_KV.andThen(KeyValueImpl::new));\n    }\n\n    @Override\n    public QueryResultsIteratorWithMetadata<KeyValue> getStateByRangeWithPagination(\n            final String startKey, final String endKey, final int pageSize, final String bookmark) {\n\n        String start = startKey;\n        String end = endKey;\n\n        if (startKey == null || startKey.isEmpty()) {\n            start = UNSPECIFIED_START_KEY;\n        }\n        if (endKey == null) {\n            end = UNSPECIFIED_END_KEY;\n        }\n\n        CompositeKey.validateSimpleKeys(start, end);\n\n        final QueryMetadata queryMetadata = QueryMetadata.newBuilder()\n                .setBookmark(bookmark)\n                .setPageSize(pageSize)\n                .build();\n\n        return executeGetStateByRangeWithMetadata(\"\", start, end, queryMetadata.toByteString());\n    }\n\n    private QueryResultsIteratorWithMetadataImpl<KeyValue> executeGetStateByRangeWithMetadata(\n            final String collection, final String startKey, final String endKey, final ByteString metadata) {\n\n        final ByteString payload = GetStateByRange.newBuilder()\n                .setCollection(collection)\n                .setStartKey(startKey)\n                .setEndKey(endKey)\n                .setMetadata(metadata)\n                .build()\n                .toByteString();\n\n        final ChaincodeMessage requestMessage =\n                ChaincodeMessageFactory.newEventMessage(GET_STATE_BY_RANGE, channelId, txId, payload);\n\n        final ByteString response = this.handler.invoke(requestMessage);\n\n        return new QueryResultsIteratorWithMetadataImpl<>(\n                this.handler, getChannelId(), getTxId(), response, QUERY_RESULT_BYTES_TO_KV.andThen(KeyValueImpl::new));\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(final String compositeKey) {\n\n        CompositeKey key;\n\n        if (compositeKey.startsWith(CompositeKey.NAMESPACE)) {\n            key = CompositeKey.parseCompositeKey(compositeKey);\n        } else {\n            key = new CompositeKey(compositeKey);\n        }\n\n        return getStateByPartialCompositeKey(key);\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(\n            final String objectType, final String... attributes) {\n        return getStateByPartialCompositeKey(new CompositeKey(objectType, attributes));\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(final CompositeKey compositeKey) {\n\n        String cKeyAsString;\n\n        if (compositeKey == null) {\n            cKeyAsString = new CompositeKey(UNSPECIFIED_START_KEY).toString();\n        } else {\n            cKeyAsString = compositeKey.toString();\n        }\n\n        return executeGetStateByRange(\"\", cKeyAsString, cKeyAsString + MAX_UNICODE_RUNE);\n    }\n\n    @Override\n    public QueryResultsIteratorWithMetadata<KeyValue> getStateByPartialCompositeKeyWithPagination(\n            final CompositeKey compositeKey, final int pageSize, final String bookmark) {\n\n        String cKeyAsString;\n\n        if (compositeKey == null) {\n            cKeyAsString = new CompositeKey(UNSPECIFIED_START_KEY).toString();\n        } else {\n            cKeyAsString = compositeKey.toString();\n        }\n\n        final QueryMetadata queryMetadata = QueryMetadata.newBuilder()\n                .setBookmark(bookmark)\n                .setPageSize(pageSize)\n                .build();\n\n        return executeGetStateByRangeWithMetadata(\n                \"\", cKeyAsString, cKeyAsString + MAX_UNICODE_RUNE, queryMetadata.toByteString());\n    }\n\n    @Override\n    public CompositeKey createCompositeKey(final String objectType, final String... attributes) {\n        return new CompositeKey(objectType, attributes);\n    }\n\n    @Override\n    public CompositeKey splitCompositeKey(final String compositeKey) {\n        return CompositeKey.parseCompositeKey(compositeKey);\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getQueryResult(final String query) {\n\n        final ByteString requestPayload = GetQueryResult.newBuilder()\n                .setCollection(\"\")\n                .setQuery(query)\n                .build()\n                .toByteString();\n        final ChaincodeMessage requestMessage =\n                ChaincodeMessageFactory.newEventMessage(GET_QUERY_RESULT, channelId, txId, requestPayload);\n        final ByteString response = handler.invoke(requestMessage);\n\n        return new QueryResultsIteratorImpl<>(\n                this.handler, channelId, txId, response, QUERY_RESULT_BYTES_TO_KV.andThen(KeyValueImpl::new));\n    }\n\n    @Override\n    public QueryResultsIteratorWithMetadata<KeyValue> getQueryResultWithPagination(\n            final String query, final int pageSize, final String bookmark) {\n\n        final ByteString queryMetadataPayload = QueryMetadata.newBuilder()\n                .setBookmark(bookmark)\n                .setPageSize(pageSize)\n                .build()\n                .toByteString();\n        final ByteString requestPayload = GetQueryResult.newBuilder()\n                .setCollection(\"\")\n                .setQuery(query)\n                .setMetadata(queryMetadataPayload)\n                .build()\n                .toByteString();\n        final ChaincodeMessage requestMessage =\n                ChaincodeMessageFactory.newEventMessage(GET_QUERY_RESULT, channelId, txId, requestPayload);\n        final ByteString response = handler.invoke(requestMessage);\n\n        return new QueryResultsIteratorWithMetadataImpl<>(\n                this.handler, channelId, txId, response, QUERY_RESULT_BYTES_TO_KV.andThen(KeyValueImpl::new));\n    }\n\n    @Override\n    public QueryResultsIterator<KeyModification> getHistoryForKey(final String key) {\n\n        final ByteString requestPayload = GetQueryResult.newBuilder()\n                .setCollection(\"\")\n                .setQuery(key)\n                .build()\n                .toByteString();\n        final ChaincodeMessage requestMessage =\n                ChaincodeMessageFactory.newEventMessage(GET_HISTORY_FOR_KEY, channelId, txId, requestPayload);\n        final ByteString response = handler.invoke(requestMessage);\n\n        return new QueryResultsIteratorImpl<>(\n                this.handler,\n                channelId,\n                txId,\n                response,\n                QUERY_RESULT_BYTES_TO_KEY_MODIFICATION.andThen(KeyModificationImpl::new));\n    }\n\n    @Override\n    public byte[] getPrivateData(final String collection, final String key) {\n        validateCollection(collection);\n        return this.handler\n                .invoke(ChaincodeMessageFactory.newGetStateEventMessage(channelId, txId, collection, key))\n                .toByteArray();\n    }\n\n    @Override\n    public byte[] getPrivateDataHash(final String collection, final String key) {\n\n        validateCollection(collection);\n\n        final ByteString requestPayload = GetState.newBuilder()\n                .setCollection(collection)\n                .setKey(key)\n                .build()\n                .toByteString();\n        final ChaincodeMessage requestMessage =\n                ChaincodeMessageFactory.newEventMessage(GET_PRIVATE_DATA_HASH, channelId, txId, requestPayload);\n\n        return handler.invoke(requestMessage).toByteArray();\n    }\n\n    @Override\n    @SuppressWarnings(\"PMD.ReturnEmptyCollectionRatherThanNull\")\n    public byte[] getPrivateDataValidationParameter(final String collection, final String key) {\n        validateCollection(collection);\n\n        final ByteString payload = handler.invoke(\n                ChaincodeMessageFactory.newGetStateMetadataEventMessage(channelId, txId, collection, key));\n        try {\n            final StateMetadataResult stateMetadataResult = StateMetadataResult.parseFrom(payload);\n            final Map<String, ByteString> stateMetadataMap = new HashMap<>();\n            stateMetadataResult\n                    .getEntriesList()\n                    .forEach(entry -> stateMetadataMap.put(entry.getMetakey(), entry.getValue()));\n\n            if (stateMetadataMap.containsKey(MetaDataKeys.VALIDATION_PARAMETER.toString())) {\n                return stateMetadataMap\n                        .get(MetaDataKeys.VALIDATION_PARAMETER.toString())\n                        .toByteArray();\n            }\n        } catch (final InvalidProtocolBufferException e) {\n            LOGGER.severe(() -> String.format(\"[%-8.8s] unmarshalling error\", txId));\n            throw new UncheckedIOException(\"Error unmarshalling StateMetadataResult.\", e);\n        }\n\n        return null;\n    }\n\n    @Override\n    public void putPrivateData(final String collection, final String key, final byte[] value) {\n        validateKey(key);\n        validateCollection(collection);\n        this.handler.invoke(ChaincodeMessageFactory.newPutStateEventMessage(\n                channelId, txId, collection, key, ByteString.copyFrom(value)));\n    }\n\n    @Override\n    public void setPrivateDataValidationParameter(final String collection, final String key, final byte[] value) {\n        validateKey(key);\n        validateCollection(collection);\n        final ChaincodeMessage msg = ChaincodeMessageFactory.newPutStateMetadataEventMessage(\n                channelId,\n                txId,\n                collection,\n                key,\n                MetaDataKeys.VALIDATION_PARAMETER.toString(),\n                ByteString.copyFrom(value));\n        this.handler.invoke(msg);\n    }\n\n    @Override\n    public void delPrivateData(final String collection, final String key) {\n        validateCollection(collection);\n        final ChaincodeMessage msg =\n                ChaincodeMessageFactory.newDeleteStateEventMessage(channelId, txId, collection, key);\n        this.handler.invoke(msg);\n    }\n\n    @Override\n    public void purgePrivateData(final String collection, final String key) {\n        validateCollection(collection);\n        final ChaincodeMessage msg =\n                ChaincodeMessageFactory.newPurgeStateEventMessage(channelId, txId, collection, key);\n        this.handler.invoke(msg);\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getPrivateDataByRange(\n            final String collection, final String startKey, final String endKey) {\n        String start = startKey;\n        String end = endKey;\n\n        validateCollection(collection);\n        if (startKey == null || startKey.isEmpty()) {\n            start = UNSPECIFIED_START_KEY;\n        }\n        if (endKey == null) {\n            end = UNSPECIFIED_END_KEY;\n        }\n        CompositeKey.validateSimpleKeys(start, end);\n\n        return executeGetStateByRange(collection, start, end);\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(\n            final String collection, final String compositeKey) {\n\n        CompositeKey key;\n\n        if (compositeKey == null) {\n            key = new CompositeKey(\"\");\n        } else if (compositeKey.startsWith(CompositeKey.NAMESPACE)) {\n            key = CompositeKey.parseCompositeKey(compositeKey);\n        } else {\n            key = new CompositeKey(compositeKey);\n        }\n\n        return getPrivateDataByPartialCompositeKey(collection, key);\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(\n            final String collection, final CompositeKey compositeKey) {\n        String cKeyAsString;\n        if (compositeKey == null) {\n            cKeyAsString = new CompositeKey(UNSPECIFIED_START_KEY).toString();\n        } else {\n            cKeyAsString = compositeKey.toString();\n        }\n\n        return executeGetStateByRange(collection, cKeyAsString, cKeyAsString + MAX_UNICODE_RUNE);\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(\n            final String collection, final String objectType, final String... attributes) {\n        return getPrivateDataByPartialCompositeKey(collection, new CompositeKey(objectType, attributes));\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getPrivateDataQueryResult(final String collection, final String query) {\n        validateCollection(collection);\n        final ByteString requestPayload = GetQueryResult.newBuilder()\n                .setCollection(collection)\n                .setQuery(query)\n                .build()\n                .toByteString();\n        final ChaincodeMessage requestMessage =\n                ChaincodeMessageFactory.newEventMessage(GET_QUERY_RESULT, channelId, txId, requestPayload);\n        final ByteString response = handler.invoke(requestMessage);\n\n        return new QueryResultsIteratorImpl<>(\n                this.handler, channelId, txId, response, QUERY_RESULT_BYTES_TO_KV.andThen(KeyValueImpl::new));\n    }\n\n    @Override\n    public Chaincode.Response invokeChaincode(\n            final String chaincodeName, final List<byte[]> args, final String channel) {\n        // internally we handle chaincode name as a composite name\n        final String compositeName;\n        if (channel != null && !isEmptyString(channel)) {\n            compositeName = chaincodeName + \"/\" + channel;\n        } else {\n            compositeName = chaincodeName;\n        }\n\n        // create invocation specification of the chaincode to invoke\n        final ByteString invocationSpecPayload = ChaincodeSpec.newBuilder()\n                .setChaincodeId(ChaincodeID.newBuilder().setName(compositeName).build())\n                .setInput(ChaincodeInput.newBuilder()\n                        .addAllArgs(args.stream().map(ByteString::copyFrom).collect(toList()))\n                        .build())\n                .build()\n                .toByteString();\n\n        final ChaincodeMessage invokeChaincodeMessage =\n                ChaincodeMessageFactory.newInvokeChaincodeMessage(this.channelId, this.txId, invocationSpecPayload);\n        final ByteString response = this.handler.invoke(invokeChaincodeMessage);\n\n        try {\n            // response message payload should be yet another chaincode\n            // message (the actual response message)\n            final ChaincodeMessage responseMessage = ChaincodeMessage.parseFrom(response);\n            // the actual response message must be of type COMPLETED\n\n            LOGGER.fine(() -> String.format(\n                    \"[%-8.8s] %s response received from other chaincode.\", txId, responseMessage.getType()));\n\n            if (responseMessage.getType() == COMPLETED) {\n                // success\n                final Response r = Response.parseFrom(responseMessage.getPayload());\n                return new Chaincode.Response(\n                        Chaincode.Response.Status.forCode(r.getStatus()),\n                        r.getMessage(),\n                        r.getPayload().toByteArray());\n            } else {\n                // error\n                final String message = responseMessage.getPayload().toStringUtf8();\n                return new Chaincode.Response(Chaincode.Response.Status.INTERNAL_SERVER_ERROR, message, null);\n            }\n        } catch (final InvalidProtocolBufferException e) {\n            throw new UncheckedIOException(e);\n        }\n    }\n\n    @Override\n    public SignedProposal getSignedProposal() {\n        return signedProposal;\n    }\n\n    @Override\n    public Instant getTxTimestamp() {\n        return txTimestamp;\n    }\n\n    @Override\n    @SuppressWarnings(\"PMD.ReturnEmptyCollectionRatherThanNull\")\n    public byte[] getCreator() {\n        if (creator == null) {\n            return null;\n        }\n        return creator.toByteArray();\n    }\n\n    @Override\n    public Map<String, byte[]> getTransient() {\n        return transientMap.entrySet().stream()\n                .collect(Collectors.toMap(Map.Entry::getKey, x -> x.getValue().toByteArray()));\n    }\n\n    @Override\n    @SuppressWarnings(\"PMD.MethodReturnsInternalArray\")\n    public byte[] getBinding() {\n        return this.binding;\n    }\n\n    private void validateKey(final String key) {\n        Objects.requireNonNull(key, \"key cannot be null\");\n        if (key.isEmpty()) {\n            throw new IllegalArgumentException(\"key cannot not be an empty string\");\n        }\n    }\n\n    private void validateCollection(final String collection) {\n        Objects.requireNonNull(collection, \"collection cannot be null\");\n        if (collection.isEmpty()) {\n            throw new IllegalArgumentException(\"collection must not be an empty string\");\n        }\n    }\n\n    @Override\n    public String getMspId() {\n        if (System.getenv().containsKey(CORE_PEER_LOCALMSPID)) {\n            return System.getenv(CORE_PEER_LOCALMSPID);\n        }\n        throw new IllegalStateException(\"CORE_PEER_LOCALMSPID is unset in chaincode process\");\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/impl/InvocationTaskExecutor.java",
    "content": "/*\n * Copyright 2019 IBM DTCC All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.impl;\n\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.RejectedExecutionHandler;\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.logging.Logger;\nimport org.hyperledger.fabric.metrics.TaskMetricsCollector;\n\n/** */\npublic final class InvocationTaskExecutor extends ThreadPoolExecutor implements TaskMetricsCollector {\n    private static Logger logger = Logger.getLogger(InvocationTaskExecutor.class.getName());\n\n    private final AtomicInteger count = new AtomicInteger();\n\n    /**\n     * @param corePoolSize\n     * @param maximumPoolSize\n     * @param keepAliveTime\n     * @param unit\n     * @param workQueue\n     * @param factory\n     * @param handler\n     */\n    public InvocationTaskExecutor(\n            final int corePoolSize,\n            final int maximumPoolSize,\n            final long keepAliveTime,\n            final TimeUnit unit,\n            final BlockingQueue<Runnable> workQueue,\n            final ThreadFactory factory,\n            final RejectedExecutionHandler handler) {\n        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, factory, handler);\n        prestartCoreThread();\n        logger.info(\"Thread pool created\");\n    }\n\n    @Override\n    protected void beforeExecute(final Thread thread, final Runnable task) {\n        super.beforeExecute(thread, task);\n        count.incrementAndGet();\n    }\n\n    @Override\n    protected void afterExecute(final Runnable task, final Throwable throwable) {\n        count.decrementAndGet();\n        super.afterExecute(task, throwable);\n    }\n\n    @Override\n    public int getCurrentTaskCount() {\n        return count.get();\n    }\n\n    @Override\n    public int getCurrentQueueCount() {\n        return this.getQueue().size();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/impl/InvocationTaskManager.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.impl;\n\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.READY;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.REGISTERED;\n\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.CompletableFuture;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.RejectedExecutionException;\nimport java.util.concurrent.RejectedExecutionHandler;\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.function.Consumer;\nimport java.util.logging.Logger;\nimport org.hyperledger.fabric.Logging;\nimport org.hyperledger.fabric.metrics.Metrics;\nimport org.hyperledger.fabric.protos.peer.ChaincodeID;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type;\nimport org.hyperledger.fabric.shim.ChaincodeBase;\n\n/**\n * The InvocationTask Manager handles the message level communication with the peer.\n *\n * <p>In the current 1.4 Fabric Protocol this is in practice a singleton - because the peer will ignore multiple\n * 'register' calls. And an instance of this will be created per register call for a given chaincodeID.\n */\n@SuppressWarnings(\"PMD.MoreThanOneLogger\")\npublic final class InvocationTaskManager {\n\n    private static final Logger LOGGER = Logger.getLogger(InvocationTaskManager.class.getName());\n    private static final Logger PERFLOGGER = Logger.getLogger(Logging.PERFLOGGER);\n    private static final String CANNOT_HANDLE_FORMAT = \"[%-8.8s] Received %s: cannot handle\";\n    private static final int SHUTDOWN_TIMEOUT = 60;\n\n    // Keeping a map here of the tasks that are currently ongoing, and the key\n    //\n    // Key = txid + channleid\n    // One task = one transaction invocation\n    private final Map<String, ChaincodeInvocationTask> innvocationTasks = new ConcurrentHashMap<>();\n\n    // Way to send back the events and data that make up the requests\n    private Consumer<ChaincodeMessage> outgoingMessage;\n\n    // references to the chaincode, and the chaincode id\n    private final ChaincodeBase chaincode;\n    private final ChaincodeID chaincodeId;\n\n    // Thread Pool creation and settings\n    private final int queueSize;\n    private final int maximumPoolSize;\n    private final int corePoolSize;\n    private final long keepAliveTime;\n    private static final TimeUnit UNIT = TimeUnit.MILLISECONDS;\n    private final BlockingQueue<Runnable> workQueue;\n\n    // Minor customization of the ThreadFactory to give a more recognizable name to the threads\n    private final ThreadFactory threadFactory = new ThreadFactory() {\n        private final AtomicInteger next = new AtomicInteger(0);\n\n        @Override\n        public Thread newThread(final Runnable r) {\n            Thread thread = Executors.defaultThreadFactory().newThread(r);\n            thread.setName(\"fabric-txinvoke:\" + next.incrementAndGet());\n            return thread;\n        }\n    };\n\n    // This is the handler that is run if the workqueue is full, usual options are\n    // you can abort (as here) or the requesting thread can do the work.\n\n    // DO NOT opt for the later. As this would then be run on the thread coming from gRPC\n    // and will block it. If there are any tasks that are waiting for a response from the\n    // peer for a ledger call, it is this gRPC thread that will do the return. but if it's\n    // waiting for a response it will block the whole chaincode.\n    private final RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();\n\n    private final InvocationTaskExecutor taskService;\n\n    /**\n     * Get an instance of the Invocation Task Manager.\n     *\n     * @param chaincode Chaincode Instance\n     * @param chaincodeId ID of the chaincode\n     * @return InvocationTaskManager\n     */\n    public static InvocationTaskManager getManager(final ChaincodeBase chaincode, final ChaincodeID chaincodeId) {\n        return new InvocationTaskManager(chaincode, chaincodeId);\n    }\n\n    /**\n     * New InvocationTaskManager.\n     *\n     * @param chaincode Chaincode Instance\n     * @param chaincodeId ID of the chaincode\n     */\n    public InvocationTaskManager(final ChaincodeBase chaincode, final ChaincodeID chaincodeId) {\n        if (chaincode == null) {\n            throw new IllegalArgumentException(\"chaincode can't be null\");\n        }\n        if (chaincodeId == null) {\n            throw new IllegalArgumentException(\"chaincodeId can't be null\");\n        }\n        this.chaincode = chaincode;\n        this.chaincodeId = chaincodeId;\n\n        // setup the thread pool here\n        final Properties props = chaincode.getChaincodeConfig();\n        queueSize = Integer.parseInt((String) props.getOrDefault(\"TP_QUEUE_SIZE\", \"5000\"));\n        maximumPoolSize = Integer.parseInt((String) props.getOrDefault(\"TP_MAX_POOL_SIZE\", \"5\"));\n        corePoolSize = Integer.parseInt((String) props.getOrDefault(\"TP_CORE_POOL_SIZE\", \"5\"));\n        keepAliveTime = Long.parseLong((String) props.getOrDefault(\"TP_KEEP_ALIVE_MS\", \"5000\"));\n\n        LOGGER.info(() -> \"Max Pool Size [TP_MAX_POOL_SIZE]\" + maximumPoolSize);\n        LOGGER.info(() -> \"Queue Size [TP_CORE_POOL_SIZE]\" + queueSize);\n        LOGGER.info(() -> \"Core Pool Size [TP_QUEUE_SIZE]\" + corePoolSize);\n        LOGGER.info(() -> \"Keep Alive Time [TP_KEEP_ALIVE_MS]\" + keepAliveTime);\n\n        workQueue = new LinkedBlockingQueue<>(queueSize);\n        taskService = new InvocationTaskExecutor(\n                corePoolSize, maximumPoolSize, keepAliveTime, UNIT, workQueue, threadFactory, handler);\n\n        Metrics.getProvider().setTaskMetricsCollector(taskService);\n    }\n\n    /**\n     * Called when a new message has arrived that needs to be processed.\n     *\n     * @throws IllegalArgumentException validation fields and arguments\n     * @param chaincodeMessage ChaincodeMessage\n     */\n    @SuppressWarnings(\"PMD.AvoidCatchingGenericException\")\n    public void onChaincodeMessage(final ChaincodeMessage chaincodeMessage) {\n        if (null == chaincodeMessage) {\n            throw new IllegalArgumentException(\"chaincodeMessage is null\");\n        }\n        LOGGER.fine(() ->\n                String.format(\"[%-8.8s] %s\", chaincodeMessage.getTxid(), ChaincodeBase.toJsonString(chaincodeMessage)));\n        try {\n            processChaincodeMessage(chaincodeMessage);\n        } catch (final RuntimeException e) {\n            // catch any issues with say the comms dropping or something else completely\n            // unknown\n            // and shutdown the pool\n            this.shutdown();\n            throw e;\n        }\n    }\n\n    private void processChaincodeMessage(final ChaincodeMessage chaincodeMessage) {\n        final Type msgType = chaincodeMessage.getType();\n\n        switch (chaincode.getState()) {\n            case CREATED:\n                if (msgType == REGISTERED) {\n                    chaincode.setState(ChaincodeBase.CCState.ESTABLISHED);\n                    LOGGER.fine(() -> String.format(\n                            \"[%-8.8s] Received REGISTERED: moving to established state\", chaincodeMessage.getTxid()));\n                } else {\n                    LOGGER.warning(() -> String.format(CANNOT_HANDLE_FORMAT, chaincodeMessage.getTxid(), msgType));\n                }\n                break;\n            case ESTABLISHED:\n                if (msgType == READY) {\n                    chaincode.setState(ChaincodeBase.CCState.READY);\n                    LOGGER.fine(() -> String.format(\n                            \"[%-8.8s] Received READY: ready for invocations\", chaincodeMessage.getTxid()));\n                } else {\n                    LOGGER.warning(() -> String.format(CANNOT_HANDLE_FORMAT, chaincodeMessage.getTxid(), msgType));\n                }\n                break;\n            case READY:\n                handleMsg(chaincodeMessage, msgType);\n                break;\n        }\n    }\n\n    /**\n     * Key method to take the message, determine if it is a new transaction or an answer (good or bad) to a stub api.\n     *\n     * @param message\n     * @param msgType\n     */\n    private void handleMsg(final ChaincodeMessage message, final Type msgType) {\n        LOGGER.fine(() -> String.format(\"[%-8.8s] Received %s\", message.getTxid(), msgType.toString()));\n        switch (msgType) {\n            case RESPONSE:\n            case ERROR:\n                sendToTask(message);\n                break;\n            case INIT:\n            case TRANSACTION:\n                newTask(message, msgType);\n                break;\n            default:\n                LOGGER.warning(() -> String.format(CANNOT_HANDLE_FORMAT, message.getTxid(), message.getType()));\n                break;\n        }\n    }\n\n    /**\n     * Send a message from the peer to the correct task. This will be a response to something like a getState() call.\n     *\n     * @param message ChaincodeMessage from the peer\n     */\n    private void sendToTask(final ChaincodeMessage message) {\n        try {\n            PERFLOGGER.fine(() -> \"> sendToTask TX::\" + message.getTxid());\n\n            final String key = message.getChannelId() + message.getTxid();\n            final ChaincodeInvocationTask task = this.innvocationTasks.get(key);\n            if (task == null) {\n                sendFailure(message, new InterruptedException(\"Task map missing entry: \" + key));\n            } else {\n                task.postMessage(message);\n                PERFLOGGER.fine(() -> \"< sendToTask TX::\" + message.getTxid());\n            }\n        } catch (final InterruptedException e) {\n            sendFailure(message, e);\n        }\n    }\n\n    private void sendFailure(final ChaincodeMessage message, final InterruptedException e) {\n        LOGGER.severe(() -> \"Failed to send response to the task task \" + message.getTxid() + Logging.formatError(e));\n\n        final ChaincodeMessage m = ChaincodeMessageFactory.newErrorEventMessage(\n                message.getChannelId(), message.getTxid(), \"Failed to send response to task\");\n        this.outgoingMessage.accept(m);\n    }\n\n    /**\n     * Create a new task to handle this transaction function.\n     *\n     * @param message ChaincodeMessage to process\n     * @param type Type of message = INIT or INVOKE. INIT is deprecated in future versions\n     * @throws InterruptedException\n     */\n    private void newTask(final ChaincodeMessage message, final Type type) {\n        String txid = message.getTxid();\n        final ChaincodeInvocationTask task =\n                new ChaincodeInvocationTask(message, type, this.outgoingMessage, this.chaincode);\n\n        PERFLOGGER.fine(() -> \"> newTask:created TX::\" + txid);\n\n        this.innvocationTasks.put(task.getTxKey(), task);\n        try {\n            PERFLOGGER.fine(() -> \"> newTask:submitting TX::\" + txid);\n\n            // submit the task to run, with the taskService providing the\n            // threading support.\n            final CompletableFuture<Void> response = CompletableFuture.runAsync(\n                    () -> {\n                        task.call();\n                    },\n                    taskService);\n\n            // we have a future of the chaincode message that should be returned.\n            // but waiting for this does not need to block this thread\n            // it is important to wait for it however, as we need to remove it from the task\n            // list\n            response.thenRun(() -> {\n                innvocationTasks.remove(task.getTxKey());\n                PERFLOGGER.fine(() -> \"< newTask:completed TX::\" + txid);\n            });\n\n            PERFLOGGER.fine(() -> \"< newTask:submitted TX::\" + txid);\n\n        } catch (final RejectedExecutionException e) {\n            LOGGER.warning(() -> \"Failed to submit task \" + txid + Logging.formatError(e));\n            // this means that there is no way that this can be handed off to another\n            // thread for processing, and there's no space left in the queue to hold\n            // it pending\n\n            final ChaincodeMessage m = ChaincodeMessageFactory.newErrorEventMessage(\n                    message.getChannelId(), txid, \"Failed to submit task for processing\");\n            this.outgoingMessage.accept(m);\n        }\n    }\n\n    /**\n     * Set the Consumer function to be used for sending messages back to the peer.\n     *\n     * @param outgoingMessage\n     * @return InvocationTaskManager\n     */\n    public void setResponseConsumer(final Consumer<ChaincodeMessage> outgoingMessage) {\n        this.outgoingMessage = outgoingMessage;\n    }\n\n    /**\n     * Send the initial protocol message for the 'register' phase.\n     *\n     * @throws IllegalArgumentException validation fields and arguments\n     */\n    public void register() {\n        if (outgoingMessage == null) {\n            throw new IllegalArgumentException(\"outgoingMessage is null\");\n        }\n\n        LOGGER.info(() -> \"Registering new chaincode \" + this.chaincodeId);\n        chaincode.setState(ChaincodeBase.CCState.CREATED);\n        this.outgoingMessage.accept(ChaincodeMessageFactory.newRegisterChaincodeMessage(this.chaincodeId));\n    }\n\n    /** */\n    @SuppressWarnings(\"PMD.SystemPrintln\")\n    public void shutdown() {\n        // Recommended shutdown process from\n        // https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html\n        // Disable new tasks from being submitted\n        this.taskService.shutdown();\n        try {\n            // Wait a while for existing tasks to terminate\n            if (!taskService.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS)) {\n                // Cancel currently executing tasks\n                taskService.shutdownNow();\n                // Wait a while for tasks to respond to being cancelled\n                if (!taskService.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS)) {\n                    System.err.println(\"Pool did not terminate\");\n                }\n            }\n        } catch (final InterruptedException ex) {\n            // (Re-)Cancel if current thread also interrupted\n            taskService.shutdownNow();\n            // Preserve interrupt status\n            Thread.currentThread().interrupt();\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/impl/KeyModificationImpl.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.impl;\n\nimport com.google.protobuf.ByteString;\nimport java.time.Instant;\nimport org.hyperledger.fabric.shim.ledger.KeyModification;\n\npublic final class KeyModificationImpl implements KeyModification {\n\n    private final String txId;\n    private final ByteString value;\n    private final Instant timestamp;\n    private final boolean deleted;\n\n    KeyModificationImpl(final org.hyperledger.fabric.protos.ledger.queryresult.KeyModification km) {\n        this.txId = km.getTxId();\n        this.value = km.getValue();\n        this.timestamp = Instant.ofEpochSecond(\n                km.getTimestamp().getSeconds(), km.getTimestamp().getNanos());\n        this.deleted = km.getIsDelete();\n    }\n\n    @Override\n    public String getTxId() {\n        return txId;\n    }\n\n    @Override\n    public byte[] getValue() {\n        return value.toByteArray();\n    }\n\n    @Override\n    public String getStringValue() {\n        return value.toStringUtf8();\n    }\n\n    @Override\n    public Instant getTimestamp() {\n        return timestamp;\n    }\n\n    @Override\n    public boolean isDeleted() {\n        return deleted;\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = Boolean.hashCode(deleted);\n        result = prime * result + timestamp.hashCode();\n        result = prime * result + txId.hashCode();\n        result = prime * result + value.hashCode();\n        return result;\n    }\n\n    @Override\n    public boolean equals(final Object other) {\n        if (this == other) {\n            return true;\n        }\n        if (other == null) {\n            return false;\n        }\n        if (getClass() != other.getClass()) {\n            return false;\n        }\n\n        final KeyModificationImpl that = (KeyModificationImpl) other;\n        return this.deleted == that.deleted\n                && this.timestamp.equals(that.timestamp)\n                && this.txId.equals(that.txId)\n                && this.value.equals(that.value);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/impl/KeyValueImpl.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.impl;\n\nimport com.google.protobuf.ByteString;\nimport org.hyperledger.fabric.protos.ledger.queryresult.KV;\nimport org.hyperledger.fabric.shim.ledger.KeyValue;\n\nclass KeyValueImpl implements KeyValue {\n\n    private final String key;\n    private final ByteString value;\n\n    KeyValueImpl(final KV kv) {\n        this.key = kv.getKey();\n        this.value = kv.getValue();\n    }\n\n    @Override\n    public String getKey() {\n        return key;\n    }\n\n    @Override\n    public byte[] getValue() {\n        return value.toByteArray();\n    }\n\n    @Override\n    public String getStringValue() {\n        return value.toStringUtf8();\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = key.hashCode();\n        result = prime * result + value.hashCode();\n        return result;\n    }\n\n    @Override\n    public boolean equals(final Object other) {\n        if (this == other) {\n            return true;\n        }\n        if (other == null) {\n            return false;\n        }\n        if (getClass() != other.getClass()) {\n            return false;\n        }\n\n        final KeyValueImpl that = (KeyValueImpl) other;\n        return this.key.equals(that.key) && this.value.equals(that.value);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/impl/QueryResultsIteratorImpl.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.impl;\n\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.QUERY_STATE_CLOSE;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.QUERY_STATE_NEXT;\n\nimport com.google.protobuf.ByteString;\nimport com.google.protobuf.InvalidProtocolBufferException;\nimport java.io.UncheckedIOException;\nimport java.util.Collections;\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\nimport java.util.function.Function;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.QueryResponse;\nimport org.hyperledger.fabric.protos.peer.QueryResultBytes;\nimport org.hyperledger.fabric.protos.peer.QueryStateClose;\nimport org.hyperledger.fabric.protos.peer.QueryStateNext;\nimport org.hyperledger.fabric.shim.ledger.QueryResultsIterator;\n\n/**\n * This class provides an ITERABLE object of query results.\n *\n * <p>NOTE the class name is misleading - as this class is not an iterator itself, rather it implements\n * java.lang.Iterable via the QueryResultsIterator\n *\n * <p>public interface QueryResultsIterator<T> extends Iterable<T>, AutoCloseable\n *\n * @param <T>\n */\nclass QueryResultsIteratorImpl<T> implements QueryResultsIterator<T> {\n\n    private final ChaincodeInvocationTask handler;\n    private final String channelId;\n    private final String txId;\n    private Iterator<QueryResultBytes> currentIterator;\n    private QueryResponse currentQueryResponse;\n    private final Function<QueryResultBytes, T> mapper;\n\n    QueryResultsIteratorImpl(\n            final ChaincodeInvocationTask handler,\n            final String channelId,\n            final String txId,\n            final ByteString responseBuffer,\n            final Function<QueryResultBytes, T> mapper) {\n\n        try {\n            this.handler = handler;\n            this.channelId = channelId;\n            this.txId = txId;\n            this.currentQueryResponse = QueryResponse.parseFrom(responseBuffer);\n            this.currentIterator = currentQueryResponse.getResultsList().iterator();\n            this.mapper = mapper;\n        } catch (final InvalidProtocolBufferException e) {\n            throw new UncheckedIOException(e);\n        }\n    }\n\n    @Override\n    public Iterator<T> iterator() {\n        return new Iterator<>() {\n\n            @Override\n            public boolean hasNext() {\n                return currentIterator.hasNext() || currentQueryResponse.getHasMore();\n            }\n\n            @Override\n            public T next() {\n\n                // return next fetched result, if any\n                if (currentIterator.hasNext()) {\n                    return mapper.apply(currentIterator.next());\n                }\n\n                // throw exception if there are no more expected results\n                if (!currentQueryResponse.getHasMore()) {\n                    throw new NoSuchElementException();\n                }\n\n                // get more results from peer\n\n                final ByteString requestPayload = QueryStateNext.newBuilder()\n                        .setId(currentQueryResponse.getId())\n                        .build()\n                        .toByteString();\n                final ChaincodeMessage requestNextMessage =\n                        ChaincodeMessageFactory.newEventMessage(QUERY_STATE_NEXT, channelId, txId, requestPayload);\n\n                final ByteString responseMessage = QueryResultsIteratorImpl.this.handler.invoke(requestNextMessage);\n                try {\n                    currentQueryResponse = QueryResponse.parseFrom(responseMessage);\n                } catch (final InvalidProtocolBufferException e) {\n                    throw new UncheckedIOException(e);\n                }\n                currentIterator = currentQueryResponse.getResultsList().iterator();\n\n                // return next fetched result\n                return mapper.apply(currentIterator.next());\n            }\n        };\n    }\n\n    @Override\n    public void close() {\n\n        final ByteString requestPayload = QueryStateClose.newBuilder()\n                .setId(currentQueryResponse.getId())\n                .build()\n                .toByteString();\n\n        final ChaincodeMessage requestNextMessage =\n                ChaincodeMessageFactory.newEventMessage(QUERY_STATE_CLOSE, channelId, txId, requestPayload);\n        this.handler.invoke(requestNextMessage);\n\n        this.currentIterator = Collections.emptyIterator();\n        this.currentQueryResponse = QueryResponse.newBuilder().setHasMore(false).build();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/impl/QueryResultsIteratorWithMetadataImpl.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.impl;\n\nimport com.google.protobuf.ByteString;\nimport com.google.protobuf.InvalidProtocolBufferException;\nimport java.io.UncheckedIOException;\nimport java.util.function.Function;\nimport java.util.logging.Logger;\nimport org.hyperledger.fabric.protos.peer.QueryResponse;\nimport org.hyperledger.fabric.protos.peer.QueryResponseMetadata;\nimport org.hyperledger.fabric.protos.peer.QueryResultBytes;\nimport org.hyperledger.fabric.shim.ledger.QueryResultsIteratorWithMetadata;\n\n/**\n * QueryResult Iterator.\n *\n * <p>Implementation of {@link QueryResultsIteratorWithMetadata}, by extending\n * {@link org.hyperledger.fabric.shim.ledger.QueryResultsIterator} implementations, {@link QueryResultsIteratorImpl}\n *\n * @param <T>\n */\npublic final class QueryResultsIteratorWithMetadataImpl<T> extends QueryResultsIteratorImpl<T>\n        implements QueryResultsIteratorWithMetadata<T> {\n    private static final Logger LOGGER = Logger.getLogger(QueryResultsIteratorWithMetadataImpl.class.getName());\n\n    private final QueryResponseMetadata metadata;\n\n    /**\n     * @param handler\n     * @param channelId\n     * @param txId\n     * @param responseBuffer\n     * @param mapper\n     */\n    public QueryResultsIteratorWithMetadataImpl(\n            final ChaincodeInvocationTask handler,\n            final String channelId,\n            final String txId,\n            final ByteString responseBuffer,\n            final Function<QueryResultBytes, T> mapper) {\n        super(handler, channelId, txId, responseBuffer, mapper);\n        try {\n            final QueryResponse queryResponse = QueryResponse.parseFrom(responseBuffer);\n            metadata = QueryResponseMetadata.parseFrom(queryResponse.getMetadata());\n        } catch (final InvalidProtocolBufferException e) {\n            LOGGER.warning(\"can't parse response metadata\");\n            throw new UncheckedIOException(e);\n        }\n    }\n\n    @Override\n    public QueryResponseMetadata getMetadata() {\n        return metadata;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/impl/package-info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/** */\npackage org.hyperledger.fabric.shim.impl;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ledger/CompositeKey.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.ledger;\n\nimport static java.util.stream.Collectors.joining;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\npublic class CompositeKey {\n\n    private static final String DELIMITER = new String(Character.toChars(Character.MIN_CODE_POINT));\n\n    private static final String INVALID_SEGMENT_CHAR = new String(Character.toChars(Character.MAX_CODE_POINT));\n    private static final String INVALID_SEGMENT_PATTERN = String.format(\"(?:%s|%s)\", INVALID_SEGMENT_CHAR, DELIMITER);\n\n    /** */\n    public static final String NAMESPACE = DELIMITER;\n\n    private final String objectType;\n    private final List<String> attributes;\n    private final String key;\n\n    /**\n     * @param objectType\n     * @param attributes\n     */\n    public CompositeKey(final String objectType, final String... attributes) {\n        this(objectType, attributes == null ? Collections.emptyList() : Arrays.asList(attributes));\n    }\n\n    /**\n     * @param objectType\n     * @param attributes\n     */\n    public CompositeKey(final String objectType, final List<String> attributes) {\n        Objects.requireNonNull(objectType, \"objectType cannot be null\");\n        this.objectType = objectType;\n        this.attributes = attributes;\n        this.key = generateCompositeKeyString(objectType, attributes);\n    }\n\n    /** @return object type */\n    public String getObjectType() {\n        return objectType;\n    }\n\n    /** @return List of string arguments */\n    public List<String> getAttributes() {\n        return attributes;\n    }\n\n    /** */\n    @Override\n    public String toString() {\n        return key;\n    }\n\n    /**\n     * @param compositeKey\n     * @return Composite Key\n     */\n    public static CompositeKey parseCompositeKey(final String compositeKey) {\n        if (compositeKey == null) {\n            return null;\n        }\n        if (!compositeKey.startsWith(NAMESPACE)) {\n            throw CompositeKeyFormatException.forInputString(compositeKey, compositeKey, 0);\n        }\n        // relying on the fact that NAMESPACE == DELIMETER\n        final String[] segments = compositeKey.split(DELIMITER, 0);\n        return new CompositeKey(segments[1], Arrays.stream(segments).skip(2).toArray(String[]::new));\n    }\n\n    /**\n     * To ensure that simple keys do not go into composite key namespace, we validate simple key to check whether the\n     * key starts with 0x00 (which is the namespace for compositeKey). This helps in avoiding simple/composite key\n     * collisions.\n     *\n     * @param keys the list of simple keys\n     * @throws CompositeKeyFormatException if First character of the key\n     */\n    public static void validateSimpleKeys(final String... keys) {\n        for (final String key : keys) {\n            if (!key.isEmpty() && key.startsWith(NAMESPACE)) {\n                throw CompositeKeyFormatException.forSimpleKey(key);\n            }\n        }\n    }\n\n    private String generateCompositeKeyString(final String objectType, final List<String> attributes) {\n\n        // object type must be a valid composite key segment\n        validateCompositeKeySegment(objectType);\n\n        if (attributes == null || attributes.isEmpty()) {\n            return NAMESPACE + objectType + DELIMITER;\n        }\n        // the attributes must be valid composite key segments\n        attributes.forEach(this::validateCompositeKeySegment);\n\n        // return NAMESPACE + objectType + DELIMITER + (attribute + DELIMITER)*\n        return attributes.stream().collect(joining(DELIMITER, NAMESPACE + objectType + DELIMITER, DELIMITER));\n    }\n\n    private void validateCompositeKeySegment(final String segment) {\n        final Matcher matcher = Pattern.compile(INVALID_SEGMENT_PATTERN).matcher(segment);\n        if (matcher.find()) {\n            throw CompositeKeyFormatException.forInputString(segment, matcher.group(), matcher.start());\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ledger/CompositeKeyFormatException.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.ledger;\n\nfinal class CompositeKeyFormatException extends IllegalArgumentException {\n    private static final long serialVersionUID = 1L;\n\n    private CompositeKeyFormatException(final String s) {\n        super(s);\n    }\n\n    static CompositeKeyFormatException forInputString(final String s, final String group, final int index) {\n        return new CompositeKeyFormatException(\n                String.format(\"For input string '%s', found 'U+%06X' at index %d.\", s, group.codePointAt(0), index));\n    }\n\n    static CompositeKeyFormatException forSimpleKey(final String key) {\n        return new CompositeKeyFormatException(String.format(\n                \"First character of the key [%s] contains a 'U+%06X' which is not allowed\",\n                key, CompositeKey.NAMESPACE.codePointAt(0)));\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ledger/KeyModification.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.ledger;\n\n/**\n * QueryResult for history query. Holds a transaction ID, value, timestamp, and delete marker which resulted from a\n * history query.\n */\npublic interface KeyModification {\n\n    /**\n     * Returns the transaction id.\n     *\n     * @return tx id of modification\n     */\n    String getTxId();\n\n    /**\n     * Returns the key's value at the time returned by {@link #getTimestamp()}.\n     *\n     * @return value\n     */\n    byte[] getValue();\n\n    /**\n     * Returns the key's value at the time returned by {@link #getTimestamp()}, decoded as a UTF-8 string.\n     *\n     * @return value as string\n     */\n    String getStringValue();\n\n    /**\n     * Returns the timestamp of the key modification entry.\n     *\n     * @return timestamp\n     */\n    java.time.Instant getTimestamp();\n\n    /**\n     * Returns the deletion marker.\n     *\n     * @return is key was deleted\n     */\n    boolean isDeleted();\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ledger/KeyValue.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.ledger;\n\n/** Query Result associating a state key with a value. */\npublic interface KeyValue {\n\n    /**\n     * Returns the state key.\n     *\n     * @return key as string\n     */\n    String getKey();\n\n    /**\n     * Returns the state value.\n     *\n     * @return value as byte array\n     */\n    byte[] getValue();\n\n    /**\n     * Returns the state value, decoded as a UTF-8 string.\n     *\n     * @return value as string\n     */\n    String getStringValue();\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ledger/QueryResultsIterator.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.ledger;\n\n/**\n * QueryResultsIterator allows a chaincode to iterate over a set of key/value pairs returned by range, execute and\n * history queries.\n *\n * @param <T> the type of elements returned by the iterator\n */\npublic interface QueryResultsIterator<T> extends Iterable<T>, AutoCloseable {\n    @Override\n    void close();\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ledger/QueryResultsIteratorWithMetadata.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.ledger;\n\nimport org.hyperledger.fabric.protos.peer.QueryResponseMetadata;\n\n/**\n * QueryResultsIteratorWithMetadata allows a chaincode to iterate over a set of key/value pairs returned by range,\n * execute and history queries. In addition, it store {@link org.hyperledger.fabric.protos.peer.QueryResponseMetadata},\n * returned by pagination range queries\n *\n * @param <T> the type of elements returned by the iterator\n */\npublic interface QueryResultsIteratorWithMetadata<T> extends Iterable<T>, AutoCloseable {\n    /** @return Query Metadata */\n    QueryResponseMetadata getMetadata();\n\n    @Override\n    void close();\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/ledger/package-info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Provides interfaces and classes for querying state variables.\n *\n * @see org.hyperledger.fabric.shim.ChaincodeStub\n */\npackage org.hyperledger.fabric.shim.ledger;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/shim/package-info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Provides interfaces and classes required for chaincode development and state variable access.\n *\n * <p>It is possible to implement Java chaincode by extending the {@link org.hyperledger.fabric.shim.ChaincodeBase}\n * class however new projects should should implement {@link org.hyperledger.fabric.contract.ContractInterface} and use\n * the contract programming model instead.\n *\n * @see org.hyperledger.fabric.contract\n * @see org.hyperledger.fabric.shim.ChaincodeBase\n */\npackage org.hyperledger.fabric.shim;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/traces/Traces.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.traces;\n\nimport java.util.Properties;\nimport java.util.logging.Logger;\nimport org.hyperledger.fabric.traces.impl.DefaultTracesProvider;\nimport org.hyperledger.fabric.traces.impl.NullProvider;\n\n/**\n * Traces Interface.\n *\n * <p>Traces setups up the provider in use from the configuration supplied\n *\n * <p>If not enabled, nothing happens.\n */\npublic final class Traces {\n\n    private static final String CHAINCODE_TRACES_ENABLED = \"CHAINCODE_TRACES_ENABLED\";\n    private static final String CHAINCODE_TRACES_PROVIDER = \"CHAINCODE_TRACES_PROVIDER\";\n\n    private static Logger logger = Logger.getLogger(Traces.class.getName());\n\n    private static TracesProvider provider;\n\n    private Traces() {}\n\n    /**\n     * @param props the configuration of the chaincode\n     * @return The traces provider\n     */\n    @SuppressWarnings(\"PMD.AvoidCatchingGenericException\")\n    public static TracesProvider initialize(final Properties props) {\n        if (Boolean.parseBoolean((String) props.get(CHAINCODE_TRACES_ENABLED))) {\n            try {\n                logger.info(\"Traces enabled\");\n                if (props.containsKey(CHAINCODE_TRACES_PROVIDER)) {\n                    final String providerClass = (String) props.get(CHAINCODE_TRACES_PROVIDER);\n\n                    @SuppressWarnings(\"unchecked\") // it must be this type otherwise an error\n                    final Class<TracesProvider> clazz = (Class<TracesProvider>) Class.forName(providerClass);\n                    provider = clazz.getConstructor().newInstance();\n                } else {\n                    logger.info(\"Using default traces provider\");\n                    provider = new DefaultTracesProvider();\n                }\n            } catch (Exception e) {\n                throw new IllegalStateException(\"Unable to start traces\", e);\n            }\n        } else {\n            // return a 'null' provider\n            logger.info(\"Traces disabled\");\n            provider = new NullProvider();\n        }\n\n        provider.initialize(props);\n        return provider;\n    }\n\n    /** @return TracesProvider */\n    public static TracesProvider getProvider() {\n        if (provider == null) {\n            throw new IllegalStateException(\"No provider set, this should have been set\");\n        }\n        return provider;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/traces/TracesProvider.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.traces;\n\nimport io.grpc.ClientInterceptor;\nimport io.opentelemetry.api.trace.Span;\nimport java.util.Properties;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\n\n/**\n * Interface to be implemented to send traces on the chaincode to the 'backend-of-choice'.\n *\n * <p>An instance of this will be created, and provided with the resources from which chaincode specific metrics can be\n * collected. (via the no-argument constructor).\n *\n * <p>The choice of when, where and what to collect etc are within the remit of the provider.\n *\n * <p>This is the effective call sequence.\n *\n * <p>MyTracesProvider mmp = new MyTracesProvider() mmp.initialize(props_from_environment); // short while later....\n * mmp.setTaskTracesCollector(taskService);\n */\npublic interface TracesProvider {\n\n    /**\n     * Initialize method that is called immediately after creation.\n     *\n     * @param props\n     */\n    default void initialize(final Properties props) {\n        // Do nothing by default\n    }\n\n    /**\n     * Creates a span with metadata of the current chaincode execution, possibly linked to the execution arguments.\n     *\n     * @param stub the context of the chaincode execution\n     * @return a new span if traces are enabled, or null. The caller is responsible for closing explicitly the span.\n     */\n    default Span createSpan(ChaincodeStub stub) {\n        return null;\n    }\n\n    /**\n     * Creates an interceptor of gRPC messages that can be injected in processing incoming messages to extract trace\n     * information.\n     *\n     * @return a new client interceptor, or null if no interceptor is set.\n     */\n    default ClientInterceptor createInterceptor() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/traces/impl/DefaultTracesProvider.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.traces.impl;\n\nimport org.hyperledger.fabric.traces.TracesProvider;\n\npublic final class DefaultTracesProvider implements TracesProvider {}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/traces/impl/NullProvider.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.traces.impl;\n\nimport org.hyperledger.fabric.traces.TracesProvider;\n\npublic final class NullProvider implements TracesProvider {}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/traces/impl/OpenTelemetryProperties.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.traces.impl;\n\nimport io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;\nimport io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;\nimport java.time.Duration;\nimport java.util.AbstractMap;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.concurrent.TimeUnit;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nullable;\n\nfinal class OpenTelemetryProperties implements ConfigProperties {\n    private final Map<String, String> config;\n\n    @SafeVarargs\n    OpenTelemetryProperties(final Map<String, String>... arrayOfProperties) {\n        Map<String, String> config = new HashMap<>();\n        for (Map<String, String> props : arrayOfProperties) {\n            props.forEach(\n                    (key, value) -> config.put(key.toLowerCase(Locale.ROOT).replace('-', '.'), value));\n        }\n        this.config = config;\n    }\n\n    @Override\n    @Nullable public String getString(final String name) {\n        return config.get(name);\n    }\n\n    @Override\n    @Nullable public Boolean getBoolean(final String name) {\n        String value = config.get(name);\n        if (value == null || value.isEmpty()) {\n            return null;\n        }\n        return Boolean.valueOf(value);\n    }\n\n    @Override\n    @Nullable public Integer getInt(final String name) {\n        String value = config.get(name);\n        if (value == null || value.isEmpty()) {\n            return null;\n        }\n        try {\n            return Integer.valueOf(value);\n        } catch (NumberFormatException ex) {\n            throw newInvalidPropertyException(name, value, \"integer\", ex);\n        }\n    }\n\n    @Override\n    @Nullable public Long getLong(final String name) {\n        String value = config.get(name);\n        if (value == null || value.isEmpty()) {\n            return null;\n        }\n        try {\n            return Long.valueOf(value);\n        } catch (NumberFormatException ex) {\n            throw newInvalidPropertyException(name, value, \"long\", ex);\n        }\n    }\n\n    @Override\n    @Nullable public Double getDouble(final String name) {\n        String value = config.get(name);\n        if (value == null || value.isEmpty()) {\n            return null;\n        }\n        try {\n            return Double.valueOf(value);\n        } catch (NumberFormatException ex) {\n            throw newInvalidPropertyException(name, value, \"double\", ex);\n        }\n    }\n\n    @Override\n    @Nullable public Duration getDuration(final String name) {\n        String value = config.get(name);\n        if (value == null || value.isEmpty()) {\n            return null;\n        }\n        String unitString = getUnitString(value);\n        String numberString = value.substring(0, value.length() - unitString.length());\n        try {\n            long rawNumber = Long.parseLong(numberString.trim());\n            TimeUnit unit = getDurationUnit(unitString.trim())\n                    .orElseThrow(() -> new ConfigurationException(\n                            \"Invalid duration property \" + name + \"=\" + value + \". Invalid duration unit.\"));\n            return Duration.ofMillis(TimeUnit.MILLISECONDS.convert(rawNumber, unit));\n        } catch (NumberFormatException ex) {\n            var e = new ConfigurationException(\n                    \"Invalid duration property \" + name + \"=\" + value + \". Expected number, found: \" + numberString);\n            e.addSuppressed(ex);\n            throw e;\n        }\n    }\n\n    @Override\n    public List<String> getList(final String name) {\n        String value = config.get(name);\n        if (value == null) {\n            return Collections.emptyList();\n        }\n        return filterBlanksAndNulls(value.split(\",\"));\n    }\n\n    @Override\n    @SuppressWarnings(\"PMD.AvoidLiteralsInIfCondition\")\n    public Map<String, String> getMap(final String name) {\n        return getList(name).stream()\n                .map(keyValuePair -> filterBlanksAndNulls(keyValuePair.split(\"=\", 2)))\n                .map(splitKeyValuePairs -> {\n                    if (splitKeyValuePairs.size() != 2) {\n                        throw new ConfigurationException(\"Invalid map property: \" + name + \"=\" + config.get(name));\n                    }\n                    return new AbstractMap.SimpleImmutableEntry<>(splitKeyValuePairs.get(0), splitKeyValuePairs.get(1));\n                })\n                // If duplicate keys, prioritize later ones similar to duplicate system properties on a\n                // Java command line.\n                .collect(Collectors.toMap(\n                        Map.Entry::getKey, Map.Entry::getValue, (first, next) -> next, LinkedHashMap::new));\n    }\n\n    private static ConfigurationException newInvalidPropertyException(\n            final String name, final String value, final String type, final Exception cause) {\n        var e = new ConfigurationException(\n                \"Invalid value for property \" + name + \"=\" + value + \". Must be a \" + type + \".\");\n        e.addSuppressed(cause);\n        throw e;\n    }\n\n    private static List<String> filterBlanksAndNulls(final String[] values) {\n        return Arrays.stream(values).map(String::trim).filter(s -> !s.isEmpty()).collect(Collectors.toList());\n    }\n\n    /**\n     * Returns the TimeUnit associated with a unit string. Defaults to milliseconds.\n     *\n     * @param unitString the time unit as a string\n     * @return the parsed TimeUnit\n     */\n    private static Optional<TimeUnit> getDurationUnit(final String unitString) {\n        switch (unitString) {\n            case \"\": // Fallthrough expected\n            case \"ms\":\n                return Optional.of(TimeUnit.MILLISECONDS);\n            case \"s\":\n                return Optional.of(TimeUnit.SECONDS);\n            case \"m\":\n                return Optional.of(TimeUnit.MINUTES);\n            case \"h\":\n                return Optional.of(TimeUnit.HOURS);\n            case \"d\":\n                return Optional.of(TimeUnit.DAYS);\n            default:\n                return Optional.empty();\n        }\n    }\n\n    /**\n     * Fragments the 'units' portion of a config value from the 'value' portion.\n     *\n     * <p>E.g. \"1ms\" would return the string \"ms\".\n     *\n     * @param rawValue the raw value of a unit and value\n     * @return the unit string\n     */\n    private static String getUnitString(final String rawValue) {\n        int lastDigitIndex = rawValue.length() - 1;\n        while (lastDigitIndex >= 0) {\n            char c = rawValue.charAt(lastDigitIndex);\n            if (Character.isDigit(c)) {\n                break;\n            }\n            lastDigitIndex -= 1;\n        }\n        // Pull everything after the last digit.\n        return rawValue.substring(lastDigitIndex + 1);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/traces/impl/OpenTelemetryTracesProvider.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.traces.impl;\n\nimport io.grpc.ClientInterceptor;\nimport io.opentelemetry.api.OpenTelemetry;\nimport io.opentelemetry.api.trace.Span;\nimport io.opentelemetry.api.trace.SpanKind;\nimport io.opentelemetry.api.trace.Tracer;\nimport io.opentelemetry.context.Context;\nimport io.opentelemetry.instrumentation.grpc.v1_6.GrpcTelemetry;\nimport io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;\nimport io.opentelemetry.semconv.ServiceAttributes;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.hyperledger.fabric.traces.TracesProvider;\n\npublic final class OpenTelemetryTracesProvider implements TracesProvider {\n\n    private static final String TX_ID = \"transaction_id\";\n    private static final String CHANNEL_ID = \"channel_id\";\n    private static final String CORE_CHAINCODE_ID_NAME = \"CORE_CHAINCODE_ID_NAME\";\n\n    private Tracer tracer;\n    private GrpcTelemetry grpcTracer;\n\n    @Override\n    public void initialize(final Properties props) {\n        String serviceName = props.getProperty(CORE_CHAINCODE_ID_NAME, \"unknown\");\n        props.setProperty(ServiceAttributes.SERVICE_NAME.getKey(), serviceName);\n\n        OpenTelemetry openTelemetry = AutoConfiguredOpenTelemetrySdk.builder()\n                .addPropertiesSupplier(() -> getOpenTelemetryProperties(props))\n                .build()\n                .getOpenTelemetrySdk();\n\n        tracer = openTelemetry.getTracerProvider().get(\"org.hyperledger.traces\");\n        grpcTracer = GrpcTelemetry.create(openTelemetry);\n    }\n\n    private Map<String, String> getOpenTelemetryProperties(final Properties props) {\n        Map<String, String> results = new HashMap<>(System.getenv());\n\n        Properties systemProps = System.getProperties();\n        systemProps.stringPropertyNames().forEach(key -> results.put(key, systemProps.getProperty(key)));\n\n        props.stringPropertyNames().forEach(key -> results.put(key, props.getProperty(key)));\n\n        return results;\n    }\n\n    @Override\n    public Span createSpan(final ChaincodeStub stub) {\n        Context parentContext = Context.current();\n        return tracer.spanBuilder(stub.getFunction())\n                .setSpanKind(SpanKind.INTERNAL)\n                .setAttribute(TX_ID, stub.getTxId())\n                .setAttribute(CHANNEL_ID, stub.getChannelId())\n                .setParent(parentContext)\n                .startSpan();\n    }\n\n    @Override\n    public ClientInterceptor createInterceptor() {\n        return grpcTracer.createClientInterceptor();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/traces/impl/package-info.java",
    "content": "/*\n * Copyright 2023 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.traces.impl;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/traces/package-info.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Supports collection of traces\n *\n * <p>This creates traces at the root level of chaincode calls.\n *\n * <p>To enable traces ensure that there is a standard format Java properties file called `config.props` in the root of\n * your contract code. For example this path\n *\n * <pre>\n * myjava - contract - project / java / src / main / resources / config.props\n * </pre>\n *\n * This should contain the following\n *\n * <pre>\n * CHAINCODE_TRACES_ENABLED=true\n * </pre>\n *\n * The traces enabled flag will turn on default traces logging. (it's off by default).\n *\n * <p>If no file is supplied traces are not enabled, the values shown for the thread pool are used.\n *\n * <p>Open Telemetry To use Open Telemetry, set the following properties:\n *\n * <pre>\n * CHAINCODE_TRACES_ENABLED=true\n * CHAINCODE_TRACES_PROVIDER=org.hyperledger.fabric.traces.impl.OpenTelemetryTracesProvider\n * </pre>\n *\n * Additionally, you can set properties after the specification:\n * https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/sdk-environment-variables.md\n *\n * <p>Example:\n *\n * <pre>\n * OTEL_EXPORTER_OTLP_ENDPOINT=otelcollector:4317\n * OTEL_EXPORTER_OTLP_INSECURE=true\n * </pre>\n */\npackage org.hyperledger.fabric.traces;\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/resources/contract-schema.json",
    "content": "{\n    \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n    \"type\": \"object\",\n    \"title\": \"Hyperledger Fabric Contract Definition JSON Schema\",\n    \"required\": [\n        \"info\",\n        \"contracts\"\n    ],\n    \"properties\": {\n        \"info\": {\n            \"$ref\": \"#/definitions/info\"\n        },\n        \"contracts\": {\n            \"type\": \"object\",\n            \"patternProperties\": {\n                \"^.*$\": {\n                    \"$ref\": \"#/definitions/contract\"\n                }\n            }\n        },\n        \"components\": {\n            \"$ref\": \"#/definitions/components\"\n        }\n    },\n    \"definitions\": {\n        \"info\": {\n            \"type\": \"object\",\n            \"description\": \"General information about the API.\",\n            \"required\": [\n                \"version\",\n                \"title\"\n            ],\n            \"properties\": {\n                \"title\": {\n                    \"type\": \"string\",\n                    \"description\": \"A unique and precise title of the API.\"\n                },\n                \"version\": {\n                    \"type\": \"string\",\n                    \"description\": \"A semantic version number of the API.\"\n                },\n                \"description\": {\n                    \"type\": \"string\",\n                    \"description\": \"A longer description of the API. Should be different from the title.  GitHub Flavored Markdown is allowed.\"\n                },\n                \"termsOfService\": {\n                    \"type\": \"string\",\n                    \"description\": \"The terms of service for the API.\"\n                },\n                \"contact\": {\n                    \"$ref\": \"#/definitions/contact\"\n                },\n                \"license\": {\n                    \"$ref\": \"#/definitions/license\"\n                }\n            }\n        },\n        \"contact\": {\n            \"type\": \"object\",\n            \"description\": \"Contact information for the owners of the API.\",\n            \"properties\": {\n                \"name\": {\n                    \"type\": \"string\",\n                    \"description\": \"The identifying name of the contact person/organization.\"\n                },\n                \"url\": {\n                    \"type\": \"string\",\n                    \"description\": \"The URL pointing to the contact information.\",\n                    \"format\": \"uri\"\n                },\n                \"email\": {\n                    \"type\": \"string\",\n                    \"description\": \"The email address of the contact person/organization.\",\n                    \"format\": \"email\"\n                }\n            }\n        },\n        \"license\": {\n            \"type\": \"object\",\n            \"required\": [\n                \"name\"\n            ],\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"name\": {\n                    \"type\": \"string\",\n                    \"description\": \"The name of the license type. It's encouraged to use an OSI compatible license.\"\n                },\n                \"url\": {\n                    \"type\": \"string\",\n                    \"description\": \"The URL pointing to the license.\",\n                    \"format\": \"uri\"\n                }\n            }\n        },\n        \"contract\": {\n            \"type\": \"object\",\n            \"description\": \"\",\n            \"required\": [\n                \"name\",\n                \"transactions\"\n            ],\n            \"properties\": {\n                \"info\": {\n                    \"$ref\": \"#/definitions/info\"\n                },\n                \"name\": {\n                    \"type\": \"string\",\n                    \"description\": \"A unique and precise title of the API.\"\n                },\n                \"transactions\": {\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/transaction\"\n                    }\n                }\n            }\n        },\n        \"objecttype\": {\n            \"type\": \"object\",\n            \"description\": \"A complex type used in a domain\",\n            \"required\": [\n                \"$id\",\n                \"properties\"\n            ],\n            \"properties\": {\n                \"$id\": {\n                    \"type\": \"string\"\n                },\n                \"properties\": {\n                    \"^.*$\": {\n                        \"$ref\": \"#/definitions/schema\"\n                    }\n                },\n                \"required\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/definitions/stringArray\"\n                }\n            }\n        },\n        \"parametersList\": {\n            \"type\": \"array\",\n            \"description\": \"The parameters needed to send a valid API call.\",\n            \"additionalItems\": false,\n            \"items\": {\n                \"oneOf\": [\n                    {\n                        \"$ref\": \"#/definitions/parameter\"\n                    },\n                    {\n                        \"$ref\": \"#/definitions/jsonReference\"\n                    }\n                ]\n            },\n            \"uniqueItems\": true\n        },\n        \"transaction\": {\n            \"type\": \"object\",\n            \"description\": \"single transaction specification\",\n            \"required\": [\n                \"name\"\n            ],\n            \"properties\": {\n                \"name\": {\n                    \"type\": \"string\",\n                    \"description\": \"name of the transaction \"\n                },\n                \"tag\": {\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"type\": \"string\",\n                        \"description\": \"free format tags\"\n                    }\n                },\n                \"parameters\": {\n                    \"$ref\": \"#/definitions/parametersList\"\n                },\n                \"returns\": {\n                    \"$ref\": \"#/definitions/schema\"\n                }\n            }\n        },\n        \"parameter\": {\n            \"type\": \"object\",\n            \"required\": [\n                \"name\",\n                \"schema\"\n            ],\n            \"properties\": {\n                \"description\": {\n                    \"type\": \"string\",\n                    \"description\": \"A brief description of the parameter. This could contain examples of use.  GitHub Flavored Markdown is allowed.\"\n                },\n                \"name\": {\n                    \"type\": \"string\",\n                    \"description\": \"The name of the parameter.\"\n                },\n                \"required\": {\n                    \"type\": \"boolean\",\n                    \"description\": \"Determines whether or not this parameter is required or optional.\",\n                    \"default\": false\n                },\n                \"schema\": {\n                    \"$ref\": \"#/definitions/schema\"\n                }\n            },\n            \"additionalProperties\": false\n        },\n        \"jsonReference\": {\n            \"type\": \"object\",\n            \"required\": [\n                \"$ref\"\n            ],\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"$ref\": {\n                    \"type\": \"string\"\n                }\n            }\n        },\n        \"schema\": {\n            \"type\": \"object\",\n            \"description\": \"A deterministic version of a JSON Schema object.\",\n            \"properties\": {\n                \"$ref\": {\n                    \"type\": \"string\"\n                },\n                \"format\": {\n                    \"type\": \"string\"\n                },\n                \"title\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/properties/title\"\n                },\n                \"description\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/properties/description\"\n                },\n                \"default\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/properties/default\"\n                },\n                \"multipleOf\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/properties/multipleOf\"\n                },\n                \"maximum\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/properties/maximum\"\n                },\n                \"exclusiveMaximum\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/properties/exclusiveMaximum\"\n                },\n                \"minimum\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/properties/minimum\"\n                },\n                \"exclusiveMinimum\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/properties/exclusiveMinimum\"\n                },\n                \"maxLength\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/definitions/positiveInteger\"\n                },\n                \"minLength\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0\"\n                },\n                \"pattern\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/properties/pattern\"\n                },\n                \"maxItems\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/definitions/positiveInteger\"\n                },\n                \"minItems\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0\"\n                },\n                \"uniqueItems\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/properties/uniqueItems\"\n                },\n                \"maxProperties\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/definitions/positiveInteger\"\n                },\n                \"minProperties\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0\"\n                },\n                \"required\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/definitions/stringArray\"\n                },\n                \"enum\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/properties/enum\"\n                },\n                \"additionalProperties\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/schema\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        }\n                    ],\n                    \"default\": {}\n                },\n                \"type\": {\n                    \"$ref\": \"http://json-schema.org/draft-04/schema#/properties/type\"\n                },\n                \"items\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/schema\"\n                        },\n                        {\n                            \"type\": \"array\",\n                            \"minItems\": 1,\n                            \"items\": {\n                                \"$ref\": \"#/definitions/schema\"\n                            }\n                        }\n                    ],\n                    \"default\": {}\n                },\n                \"allOf\": {\n                    \"type\": \"array\",\n                    \"minItems\": 1,\n                    \"items\": {\n                        \"$ref\": \"#/definitions/schema\"\n                    }\n                },\n                \"properties\": {\n                    \"type\": \"object\",\n                    \"additionalProperties\": {\n                        \"$ref\": \"#/definitions/schema\"\n                    },\n                    \"default\": {}\n                },\n                \"discriminator\": {\n                    \"type\": \"string\"\n                },\n                \"readOnly\": {\n                    \"type\": \"boolean\",\n                    \"default\": false\n                },\n                \"example\": {}\n            },\n            \"additionalProperties\": false\n        },\n        \"components\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"schemas\": {\n                    \"type\": \"object\",\n                    \"patternProperties\": {\n                        \"^.*$\": {\n                            \"$ref\": \"#/definitions/objecttype\"\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/main/resources/json-schema-draft-04-schema.json",
    "content": "{\n    \"id\": \"http://json-schema.org/draft-04/schema#\",\n    \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n    \"description\": \"Core schema meta-schema\",\n    \"definitions\": {\n        \"schemaArray\": {\n            \"type\": \"array\",\n            \"minItems\": 1,\n            \"items\": { \"$ref\": \"#\" }\n        },\n        \"positiveInteger\": {\n            \"type\": \"integer\",\n            \"minimum\": 0\n        },\n        \"positiveIntegerDefault0\": {\n            \"allOf\": [ { \"$ref\": \"#/definitions/positiveInteger\" }, { \"default\": 0 } ]\n        },\n        \"simpleTypes\": {\n            \"enum\": [ \"array\", \"boolean\", \"integer\", \"null\", \"number\", \"object\", \"string\" ]\n        },\n        \"stringArray\": {\n            \"type\": \"array\",\n            \"items\": { \"type\": \"string\" },\n            \"minItems\": 1,\n            \"uniqueItems\": true\n        }\n    },\n    \"type\": \"object\",\n    \"properties\": {\n        \"id\": {\n            \"type\": \"string\"\n        },\n        \"$schema\": {\n            \"type\": \"string\"\n        },\n        \"title\": {\n            \"type\": \"string\"\n        },\n        \"description\": {\n            \"type\": \"string\"\n        },\n        \"default\": {},\n        \"multipleOf\": {\n            \"type\": \"number\",\n            \"minimum\": 0,\n            \"exclusiveMinimum\": true\n        },\n        \"maximum\": {\n            \"type\": \"number\"\n        },\n        \"exclusiveMaximum\": {\n            \"type\": \"boolean\",\n            \"default\": false\n        },\n        \"minimum\": {\n            \"type\": \"number\"\n        },\n        \"exclusiveMinimum\": {\n            \"type\": \"boolean\",\n            \"default\": false\n        },\n        \"maxLength\": { \"$ref\": \"#/definitions/positiveInteger\" },\n        \"minLength\": { \"$ref\": \"#/definitions/positiveIntegerDefault0\" },\n        \"pattern\": {\n            \"type\": \"string\",\n            \"format\": \"regex\"\n        },\n        \"additionalItems\": {\n            \"anyOf\": [\n                { \"type\": \"boolean\" },\n                { \"$ref\": \"#\" }\n            ],\n            \"default\": {}\n        },\n        \"items\": {\n            \"anyOf\": [\n                { \"$ref\": \"#\" },\n                { \"$ref\": \"#/definitions/schemaArray\" }\n            ],\n            \"default\": {}\n        },\n        \"maxItems\": { \"$ref\": \"#/definitions/positiveInteger\" },\n        \"minItems\": { \"$ref\": \"#/definitions/positiveIntegerDefault0\" },\n        \"uniqueItems\": {\n            \"type\": \"boolean\",\n            \"default\": false\n        },\n        \"maxProperties\": { \"$ref\": \"#/definitions/positiveInteger\" },\n        \"minProperties\": { \"$ref\": \"#/definitions/positiveIntegerDefault0\" },\n        \"required\": { \"$ref\": \"#/definitions/stringArray\" },\n        \"additionalProperties\": {\n            \"anyOf\": [\n                { \"type\": \"boolean\" },\n                { \"$ref\": \"#\" }\n            ],\n            \"default\": {}\n        },\n        \"definitions\": {\n            \"type\": \"object\",\n            \"additionalProperties\": { \"$ref\": \"#\" },\n            \"default\": {}\n        },\n        \"properties\": {\n            \"type\": \"object\",\n            \"additionalProperties\": { \"$ref\": \"#\" },\n            \"default\": {}\n        },\n        \"patternProperties\": {\n            \"type\": \"object\",\n            \"additionalProperties\": { \"$ref\": \"#\" },\n            \"default\": {}\n        },\n        \"dependencies\": {\n            \"type\": \"object\",\n            \"additionalProperties\": {\n                \"anyOf\": [\n                    { \"$ref\": \"#\" },\n                    { \"$ref\": \"#/definitions/stringArray\" }\n                ]\n            }\n        },\n        \"enum\": {\n            \"type\": \"array\",\n            \"minItems\": 1,\n            \"uniqueItems\": true\n        },\n        \"type\": {\n            \"anyOf\": [\n                { \"$ref\": \"#/definitions/simpleTypes\" },\n                {\n                    \"type\": \"array\",\n                    \"items\": { \"$ref\": \"#/definitions/simpleTypes\" },\n                    \"minItems\": 1,\n                    \"uniqueItems\": true\n                }\n            ]\n        },\n        \"format\": { \"type\": \"string\" },\n        \"allOf\": { \"$ref\": \"#/definitions/schemaArray\" },\n        \"anyOf\": { \"$ref\": \"#/definitions/schemaArray\" },\n        \"oneOf\": { \"$ref\": \"#/definitions/schemaArray\" },\n        \"not\": { \"$ref\": \"#\" }\n    },\n    \"dependencies\": {\n        \"exclusiveMaximum\": [ \"maximum\" ],\n        \"exclusiveMinimum\": [ \"minimum\" ]\n    },\n    \"default\": {}\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/ChaincodeWithoutPackageTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.READY;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.REGISTER;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\nimport org.hyperledger.fabric.shim.ChaincodeBase;\nimport org.hyperledger.fabric.shim.mock.peer.ChaincodeMockPeer;\nimport org.hyperledger.fabric.shim.mock.peer.RegisterStep;\nimport org.hyperledger.fabric.shim.mock.peer.ScenarioStep;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nfinal class ChaincodeWithoutPackageTest {\n    private ChaincodeMockPeer server;\n\n    @AfterEach\n    void afterTest() throws Exception {\n        if (server != null) {\n            server.stop();\n            server = null;\n        }\n    }\n\n    @Test\n    void testRegisterChaincodeWithoutPackage() throws Exception {\n        final ChaincodeBase cb = new EmptyChaincodeWithoutPackage();\n\n        final List<ScenarioStep> scenario = new ArrayList<>();\n        scenario.add(new RegisterStep());\n\n        server = ChaincodeMockPeer.startServer(scenario);\n\n        cb.start(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 1, 5000, TimeUnit.MILLISECONDS);\n\n        assertThat(server.getLastMessageSend().getType()).isEqualTo(READY);\n        assertThat(server.getLastMessageRcvd().getType()).isEqualTo(REGISTER);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/EmptyChaincodeWithoutPackage.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport org.hyperledger.fabric.shim.ChaincodeBase;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.hyperledger.fabric.shim.ResponseUtils;\n\npublic final class EmptyChaincodeWithoutPackage extends ChaincodeBase {\n    @Override\n    public Response init(final ChaincodeStub stub) {\n        return ResponseUtils.newSuccessResponse();\n    }\n\n    @Override\n    public Response invoke(final ChaincodeStub stub) {\n        return ResponseUtils.newSuccessResponse();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/contract/Greeting.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage contract;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\nimport org.hyperledger.fabric.contract.annotation.DataType;\nimport org.hyperledger.fabric.contract.annotation.Property;\nimport org.json.JSONObject;\n\n@DataType()\npublic final class Greeting {\n\n    @Property()\n    private String text;\n\n    @Property()\n    private int textLength;\n\n    public String getText() {\n        return text;\n    }\n\n    public void setText(final String text) {\n        this.text = text;\n    }\n\n    public int getTextLength() {\n        return textLength;\n    }\n\n    public void setTextLength(final int textLength) {\n        this.textLength = textLength;\n    }\n\n    public int getWordCount() {\n        return wordCount;\n    }\n\n    public void setWordCount(final int wordCount) {\n        this.wordCount = wordCount;\n    }\n\n    private int wordCount;\n\n    public Greeting(final String text) {\n        this.text = text;\n        this.textLength = text.length();\n        this.wordCount = text.split(\" \").length;\n    }\n\n    public static void validate(final Greeting greeting) {\n        final String text = greeting.text;\n\n        assertThat(text).as(\"greeting length\").hasSize(greeting.textLength);\n        assertThat(text.split(\" \")).as(\"word count\").hasSize(greeting.wordCount);\n    }\n\n    public String toJSONString() {\n        return new JSONObject(this).toString();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/contract/SampleContract.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage contract;\n\nimport java.util.List;\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.annotation.Contact;\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.Default;\nimport org.hyperledger.fabric.contract.annotation.Info;\nimport org.hyperledger.fabric.contract.annotation.License;\nimport org.hyperledger.fabric.contract.annotation.Transaction;\nimport org.hyperledger.fabric.shim.ChaincodeException;\n\n@Contract(\n        name = \"samplecontract\",\n        info =\n                @Info(\n                        contact = @Contact(email = \"fred@example.com\"),\n                        license = @License(name = \"fred\", url = \"http://fred.me\"),\n                        version = \"0.0.1\",\n                        title = \"samplecontract\"))\n@SuppressWarnings(\"PMD.SystemPrintln\")\n@Default()\npublic class SampleContract implements ContractInterface {\n    public static int getBeforeInvoked() {\n        return beforeInvoked;\n    }\n\n    public static int getAfterInvoked() {\n        return afterInvoked;\n    }\n\n    public static int getDoWorkInvoked() {\n        return doWorkInvoked;\n    }\n\n    public static int getT1Invoked() {\n        return t1Invoked;\n    }\n\n    public static int getI1Invoked() {\n        return i1Invoked;\n    }\n\n    public static void setBeforeInvoked(final int beforeInvoked) {\n        SampleContract.beforeInvoked = beforeInvoked;\n    }\n\n    public static void setAfterInvoked(final int afterInvoked) {\n        SampleContract.afterInvoked = afterInvoked;\n    }\n\n    public static void setDoWorkInvoked(final int doWorkInvoked) {\n        SampleContract.doWorkInvoked = doWorkInvoked;\n    }\n\n    public static void setT1Invoked(final int t1Invoked) {\n        SampleContract.t1Invoked = t1Invoked;\n    }\n\n    public static void setI1Invoked(final int i1Invoked) {\n        SampleContract.i1Invoked = i1Invoked;\n    }\n\n    private static int beforeInvoked = 0;\n    private static int afterInvoked = 0;\n    private static int doWorkInvoked = 0;\n    private static int t1Invoked = 0;\n    private static int i1Invoked = 0;\n\n    /**\n     * @param ctx\n     * @return\n     */\n    @Transaction\n    public String t5(final Context ctx) {\n        doSomeWork();\n        System.out.println(\"SampleContract::T5 Done\");\n        return null;\n    }\n\n    /**\n     * @param ctx\n     * @return\n     */\n    @Transaction(name = \"t4\")\n    public String tFour(final Context ctx) {\n\n        System.out.println(\"SampleContract::T4 Done\");\n        return \"Transaction 4\";\n    }\n\n    /**\n     * @param ctx\n     * @param exception\n     * @param message\n     * @return\n     */\n    @Transaction\n    public String t3(final Context ctx, final String exception, final String message) {\n        if (\"TransactionException\".equals(exception)) {\n            if (message.isEmpty()) {\n                throw new ChaincodeException(null, \"T3ERR1\");\n            } else {\n                throw new ChaincodeException(message, \"T3ERR1\");\n            }\n        } else {\n            throw new IllegalArgumentException(message);\n        }\n    }\n\n    /**\n     * @param ctx\n     * @return\n     */\n    @Transaction\n    public String t2(final Context ctx) {\n\n        System.out.println(\"SampleContract::T2 Done\");\n        return \"Transaction 2\";\n    }\n\n    /** @param ctx */\n    @Transaction\n    public void noReturn(final Context ctx) {\n        System.out.println(\"SampleContract::noReturn done\");\n    }\n\n    /**\n     * @param ctx\n     * @param arg1\n     * @return\n     */\n    @Transaction\n    public String t1(final Context ctx, final String arg1) {\n        t1Invoked++;\n\n        final List<String> args = ctx.getStub().getStringArgs();\n        doSomeWork();\n        System.out.println(\"SampleContract::T1 Done\");\n        return args.get(1);\n    }\n\n    /** */\n    @Override\n    public void beforeTransaction(final Context ctx) {\n        beforeInvoked++;\n    }\n\n    /** */\n    @Override\n    public void afterTransaction(final Context ctx, final Object value) {\n        afterInvoked++;\n    }\n\n    private void doSomeWork() {\n        doWorkInvoked++;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/LoggerTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric;\n\nimport org.hyperledger.fabric.contract.ContractRuntimeException;\nimport org.junit.jupiter.api.Test;\n\nclass LoggerTest {\n    @Test\n    void logger() {\n        Logger.getLogger(LoggerTest.class);\n        Logger.getLogger(LoggerTest.class.getName());\n    }\n\n    @Test\n    void testContractException() {\n        final Logger logger = Logger.getLogger(LoggerTest.class);\n\n        final ContractRuntimeException cre1 = new ContractRuntimeException(\"\");\n        logger.formatError(cre1);\n\n        final ContractRuntimeException cre2 = new ContractRuntimeException(\"\", cre1);\n        final ContractRuntimeException cre3 = new ContractRuntimeException(\"\", cre2);\n        logger.formatError(cre3);\n\n        logger.error(\"all gone wrong\");\n        logger.error(() -> \"all gone wrong\");\n    }\n\n    @Test\n    void testDebug() {\n        Logger.getLogger(LoggerTest.class).debug(\"debug message\");\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/LoggingTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric;\n\nimport static org.hamcrest.CoreMatchers.containsString;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.logging.Level;\nimport org.hamcrest.CoreMatchers;\nimport org.junit.jupiter.api.Test;\n\nfinal class LoggingTest {\n    @Test\n    void testMapLevel() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {\n\n        assertEquals(Level.SEVERE, proxyMapLevel(\"ERROR\"), \"Error maps\");\n        assertEquals(Level.SEVERE, proxyMapLevel(\"critical\"), \"Critical maps\");\n        assertEquals(Level.WARNING, proxyMapLevel(\"WARNING\"), \"Warn maps\");\n        assertEquals(Level.INFO, proxyMapLevel(\"INFO\"), \"Info maps\");\n        assertEquals(Level.CONFIG, proxyMapLevel(\" notice\"), \"Config maps\");\n        assertEquals(Level.INFO, proxyMapLevel(\" info\"), \"Info maps\");\n        assertEquals(Level.FINEST, proxyMapLevel(\"debug          \"), \"Debug maps\");\n        assertEquals(Level.INFO, proxyMapLevel(\"wibble          \"), \"Info maps\");\n        assertEquals(Level.INFO, proxyMapLevel(new Object[] {null}), \"Info maps\");\n    }\n\n    private Object proxyMapLevel(final Object... args)\n            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {\n        final Method m = Logging.class.getDeclaredMethod(\"mapLevel\", String.class);\n        m.setAccessible(true);\n        return m.invoke(null, args);\n    }\n\n    @Test\n    void testFormatError() {\n        final Exception e1 = new Exception(\"Computer says no\");\n\n        assertThat(Logging.formatError(e1), containsString(\"Computer says no\"));\n\n        final NullPointerException npe1 = new NullPointerException(\"Nothing here\");\n        npe1.initCause(e1);\n\n        assertThat(Logging.formatError(npe1), containsString(\"Computer says no\"));\n        assertThat(Logging.formatError(npe1), containsString(\"Nothing here\"));\n\n        assertThat(Logging.formatError(null), CoreMatchers.nullValue());\n    }\n\n    @Test\n    void testSetLogLevel() {\n\n        final java.util.logging.Logger l = java.util.logging.Logger.getLogger(\"org.hyperledger.fabric.test\");\n        final java.util.logging.Logger another = java.util.logging.Logger.getLogger(\"acme.wibble\");\n\n        final Level anotherLevel = another.getLevel();\n        Logging.setLogLevel(\"debug\");\n        assertThat(l.getLevel(), CoreMatchers.equalTo(Level.FINEST));\n        assertThat(another.getLevel(), CoreMatchers.equalTo(anotherLevel));\n\n        Logging.setLogLevel(\"dsomethoig\");\n        assertThat(l.getLevel(), CoreMatchers.equalTo(Level.INFO));\n        assertThat(another.getLevel(), CoreMatchers.equalTo(anotherLevel));\n\n        Logging.setLogLevel(\"ERROR\");\n        assertThat(l.getLevel(), CoreMatchers.equalTo(Level.SEVERE));\n        assertThat(another.getLevel(), CoreMatchers.equalTo(anotherLevel));\n\n        Logging.setLogLevel(\"debug\");\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/TestUtil.java",
    "content": "/*\n * Copyright 2019 IBM DTCC All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric;\n\nimport java.io.ByteArrayInputStream;\nimport java.security.KeyPair;\nimport java.security.KeyPairGenerator;\nimport java.security.cert.CertificateFactory;\nimport java.security.cert.X509Certificate;\nimport java.util.Base64;\nimport org.bouncycastle.asn1.ASN1ObjectIdentifier;\nimport org.bouncycastle.cert.X509CertificateHolder;\nimport org.bouncycastle.cert.X509v3CertificateBuilder;\nimport org.bouncycastle.operator.ContentSigner;\nimport org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;\n\npublic final class TestUtil {\n\n    private TestUtil() {}\n\n    public static final String CERT_WITHOUT_ATTRS = \"MIICXTCCAgSgAwIBAgIUeLy6uQnq8wwyElU/jCKRYz3tJiQwCgYIKoZIzj0EAwIw\"\n            + \"eTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh\"\n            + \"biBGcmFuY2lzY28xGTAXBgNVBAoTEEludGVybmV0IFdpZGdldHMxDDAKBgNVBAsT\"\n            + \"A1dXVzEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMTcwOTA4MDAxNTAwWhcNMTgw\"\n            + \"OTA4MDAxNTAwWjBdMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xp\"\n            + \"bmExFDASBgNVBAoTC0h5cGVybGVkZ2VyMQ8wDQYDVQQLEwZGYWJyaWMxDjAMBgNV\"\n            + \"BAMTBWFkbWluMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFq/90YMuH4tWugHa\"\n            + \"oyZtt4Mbwgv6CkBSDfYulVO1CVInw1i/k16DocQ/KSDTeTfgJxrX1Ree1tjpaodG\"\n            + \"1wWyM6OBhTCBgjAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAdBgNVHQ4E\"\n            + \"FgQUhKs/VJ9IWJd+wer6sgsgtZmxZNwwHwYDVR0jBBgwFoAUIUd4i/sLTwYWvpVr\"\n            + \"TApzcT8zv/kwIgYDVR0RBBswGYIXQW5pbHMtTWFjQm9vay1Qcm8ubG9jYWwwCgYI\"\n            + \"KoZIzj0EAwIDRwAwRAIgCoXaCdU8ZiRKkai0QiXJM/GL5fysLnmG2oZ6XOIdwtsC\"\n            + \"IEmCsI8Mhrvx1doTbEOm7kmIrhQwUVDBNXCWX1t3kJVN\";\n\n    public static final String CERT_WITH_ATTRS = \"MIIB6TCCAY+gAwIBAgIUHkmY6fRP0ANTvzaBwKCkMZZPUnUwCgYIKoZIzj0EAwIw\"\n            + \"GzEZMBcGA1UEAxMQZmFicmljLWNhLXNlcnZlcjAeFw0xNzA5MDgwMzQyMDBaFw0x\"\n            + \"ODA5MDgwMzQyMDBaMB4xHDAaBgNVBAMTE015VGVzdFVzZXJXaXRoQXR0cnMwWTAT\"\n            + \"BgcqhkjOPQIBBggqhkjOPQMBBwNCAATmB1r3CdWvOOP3opB3DjJnW3CnN8q1ydiR\"\n            + \"dzmuA6A2rXKzPIltHvYbbSqISZJubsy8gVL6GYgYXNdu69RzzFF5o4GtMIGqMA4G\"\n            + \"A1UdDwEB/wQEAwICBDAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTYKLTAvJJK08OM\"\n            + \"VGwIhjMQpo2DrjAfBgNVHSMEGDAWgBTEs/52DeLePPx1+65VhgTwu3/2ATAiBgNV\"\n            + \"HREEGzAZghdBbmlscy1NYWNCb29rLVByby5sb2NhbDAmBggqAwQFBgcIAQQaeyJh\"\n            + \"dHRycyI6eyJhdHRyMSI6InZhbDEifX0wCgYIKoZIzj0EAwIDSAAwRQIhAPuEqWUp\"\n            + \"svTTvBqLR5JeQSctJuz3zaqGRqSs2iW+QB3FAiAIP0mGWKcgSGRMMBvaqaLytBYo\" + \"9v3hRt1r8j8vN0pMcg==\";\n\n    public static final String CERT_WITH_DNS = \"MIICGjCCAcCgAwIBAgIRAIPRwJHVLhHK47XK0BbFZJswCgYIKoZIzj0EAwIwczEL\"\n            + \"MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG\"\n            + \"cmFuY2lzY28xGTAXBgNVBAoTEG9yZzIuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\"\n            + \"Lm9yZzIuZXhhbXBsZS5jb20wHhcNMTcwNjIzMTIzMzE5WhcNMjcwNjIxMTIzMzE5\"\n            + \"WjBbMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMN\"\n            + \"U2FuIEZyYW5jaXNjbzEfMB0GA1UEAwwWVXNlcjFAb3JnMi5leGFtcGxlLmNvbTBZ\"\n            + \"MBMGByqGSM49AgEGCCqGSM49AwEHA0IABBd9SsEiFH1/JIb3qMEPLR2dygokFVKW\"\n            + \"eINcB0Ni4TBRkfIWWUJeCANTUY11Pm/+5gs+fBTqBz8M2UzpJDVX7+2jTTBLMA4G\"\n            + \"A1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMCsGA1UdIwQkMCKAIKfUfvpGproH\"\n            + \"cwyFD+0sE3XfJzYNcif0jNwvgOUFZ4AFMAoGCCqGSM49BAMCA0gAMEUCIQC8NIMw\"\n            + \"e4ym/QRwCJb5umbONNLSVQuEpnPsJrM/ssBPvgIgQpe2oYa3yO3USro9nBHjpM3L\"\n            + \"KsFQrpVnF8O6hoHOYZQ=\";\n\n    public static final String CERT_MULTIPLE_ATTRIBUTES =\n            \"MIIChzCCAi6gAwIBAgIURilAHeqwLu/fNUv8eZoGPRh3H4IwCgYIKoZIzj0EAwIw\"\n                    + \"czELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh\"\n                    + \"biBGcmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMT\"\n                    + \"E2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTkwNzMxMTYxNzAwWhcNMjAwNzMwMTYy\"\n                    + \"MjAwWjAgMQ8wDQYDVQQLEwZjbGllbnQxDTALBgNVBAMTBHRlc3QwWTATBgcqhkjO\"\n                    + \"PQIBBggqhkjOPQMBBwNCAAR2taQK8w7D3hr3gBxCz+8eV4KSv7pFQfNjDHMMe9J9\"\n                    + \"LJwcLpVTT5hYiLLRaqQonLBxBE3Ey0FneySvFuBScas3o4HyMIHvMA4GA1UdDwEB\"\n                    + \"/wQEAwIHgDAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQi3mhXS/WzcjBniwAmPdYP\"\n                    + \"kHqVVzArBgNVHSMEJDAigCC7VXjmSEugjAB/A0S6vfMxLsUIgag9WVNwtwwebnRC\"\n                    + \"7TCBggYIKgMEBQYHCAEEdnsiYXR0cnMiOnsiYXR0cjEiOiJ2YWwxIiwiZm9vIjoi\"\n                    + \"YmFyIiwiaGVsbG8iOiJ3b3JsZCIsImhmLkFmZmlsaWF0aW9uIjoiIiwiaGYuRW5y\"\n                    + \"b2xsbWVudElEIjoidGVzdCIsImhmLlR5cGUiOiJjbGllbnQifX0wCgYIKoZIzj0E\"\n                    + \"AwIDRwAwRAIgQxEFvnZTEsf3CSZmp9IYsxcnEOtVYleOd86LAKtk1wICIH7XOPwW\"\n                    + \"/RE4Z8WLZzFei/78Oezbx6obOvBxPMsVWRe5\";\n\n    /**\n     * Function to create a certificate with dummy attributes\n     *\n     * @param attributeValue {String} value to be written to the identity attributes section of the certificate\n     * @return encodedCert {String} encoded certificate with re-written attributes\n     */\n    public static String createCertWithIdentityAttributes(final String attributeValue) throws Exception {\n\n        // Use existing certificate with attributes\n        final byte[] decodedCert = Base64.getDecoder().decode(CERT_MULTIPLE_ATTRIBUTES);\n        // Create a certificate holder and builder\n        final X509CertificateHolder certHolder = new X509CertificateHolder(decodedCert);\n        final X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(certHolder);\n\n        // special OID used by Fabric to save attributes in x.509 certificates\n        final String fabricCertOid = \"1.2.3.4.5.6.7.8.1\";\n        // Write the new attribute value\n        final byte[] extDataToWrite = attributeValue.getBytes();\n        certBuilder.replaceExtension(new ASN1ObjectIdentifier(fabricCertOid), true, extDataToWrite);\n\n        // Create a privateKey\n        final KeyPairGenerator generator = KeyPairGenerator.getInstance(\"EC\");\n        generator.initialize(384);\n        final KeyPair keyPair = generator.generateKeyPair();\n\n        // Create and build the Content Signer\n        final JcaContentSignerBuilder contentSignerBuilder = new JcaContentSignerBuilder(\"SHA256withECDSA\");\n        final ContentSigner contentSigner = contentSignerBuilder.build(keyPair.getPrivate());\n        // Build the Certificate from the certificate builder\n        final X509CertificateHolder builtCert = certBuilder.build(contentSigner);\n        final X509Certificate certificate = (X509Certificate) CertificateFactory.getInstance(\"X509\")\n                .generateCertificate(new ByteArrayInputStream(builtCert.getEncoded()));\n        return Base64.getEncoder().encodeToString(certificate.getEncoded());\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/AllTypesAsset.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract;\n\nimport org.hyperledger.fabric.contract.annotation.DataType;\nimport org.hyperledger.fabric.contract.annotation.Property;\n\n@DataType()\npublic final class AllTypesAsset {\n\n    @Property\n    private byte theByte = 125;\n\n    @Property\n    private short theShort = 30000;\n\n    @Property\n    private int theInt = 1234577123;\n\n    @Property\n    private long theLong = 12384233333123L;\n\n    @Property\n    private float theFloat = 3.1415926535_8979323846_2643383279_5028841971_6939937510_5820974944_5923078164f;\n\n    @Property\n    private double theDouble =\n            3.1415926535_8979323846_2643383279_5028841971_6939937510_5820974944_5923078164_0628620899_8628034825_3421170679d;\n\n    @Property\n    private boolean theBoolean = false;\n\n    @Property\n    private char theChar = 'a';\n\n    @Property\n    private String theString = \"Hello World\";\n\n    @Property\n    private MyType theCustomObject = new MyType().setValue(\"Hello World\");\n\n    public byte getTheByte() {\n        return theByte;\n    }\n\n    public void setTheByte(final byte aByte) {\n        this.theByte = aByte;\n    }\n\n    public short getTheShort() {\n        return theShort;\n    }\n\n    public void setTheShort(final short aShort) {\n        this.theShort = aShort;\n    }\n\n    public int getTheInt() {\n        return theInt;\n    }\n\n    public void setTheInt(final int aInt) {\n        this.theInt = aInt;\n    }\n\n    public long getTheLong() {\n        return theLong;\n    }\n\n    public void setTheLong(final long aLong) {\n        this.theLong = aLong;\n    }\n\n    public float getTheFloat() {\n        return theFloat;\n    }\n\n    public void setTheFloat(final float aFloat) {\n        this.theFloat = aFloat;\n    }\n\n    public double getTheDouble() {\n        return theDouble;\n    }\n\n    public void setTheDouble(final double aDouble) {\n        this.theDouble = aDouble;\n    }\n\n    public boolean isTheBoolean() {\n        return theBoolean;\n    }\n\n    public void setBoolean(final boolean aBoolean) {\n        this.theBoolean = aBoolean;\n    }\n\n    public char getTheChar() {\n        return theChar;\n    }\n\n    public void setTheChar(final char aChar) {\n        this.theChar = aChar;\n    }\n\n    public String getTheString() {\n        return theString;\n    }\n\n    public void setString(final String aString) {\n        this.theString = aString;\n    }\n\n    public MyType getTheCustomObject() {\n        return theCustomObject;\n    }\n\n    public void setTheCustomObject(final MyType customObject) {\n        this.theCustomObject = customObject;\n    }\n\n    @Override\n    public boolean equals(final Object other) {\n        if (!(other instanceof AllTypesAsset)) {\n            return false;\n        }\n\n        AllTypesAsset obj = (AllTypesAsset) other;\n        return theByte == obj.getTheByte()\n                && theShort == obj.getTheShort()\n                && theInt == obj.getTheInt()\n                && theLong == obj.getTheLong()\n                && theFloat == obj.getTheFloat()\n                && theDouble == obj.getTheDouble()\n                && theBoolean == obj.isTheBoolean()\n                && theString.equals(obj.getTheString());\n    }\n\n    @Override\n    public String toString() {\n        return System.lineSeparator() + \"byte=\" + theByte + System.lineSeparator() + \"short=\"\n                + theShort + System.lineSeparator() + \"int=\"\n                + theInt + System.lineSeparator() + \"long=\"\n                + theLong + System.lineSeparator() + \"float=\"\n                + theFloat + System.lineSeparator() + \"double=\"\n                + theDouble + System.lineSeparator() + \"boolean=\"\n                + theBoolean + System.lineSeparator() + \"char=\"\n                + theChar + System.lineSeparator() + \"String=\"\n                + theString + System.lineSeparator() + \"Mytype=\"\n                + theCustomObject + System.lineSeparator();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/ChaincodeStubNaiveImpl.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract;\n\nimport com.google.protobuf.ByteString;\nimport java.nio.charset.StandardCharsets;\nimport java.time.Instant;\nimport java.util.ArrayList;\nimport java.util.Base64;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.stream.Collectors;\nimport org.hyperledger.fabric.TestUtil;\nimport org.hyperledger.fabric.protos.msp.SerializedIdentity;\nimport org.hyperledger.fabric.protos.peer.ChaincodeEvent;\nimport org.hyperledger.fabric.protos.peer.SignedProposal;\nimport org.hyperledger.fabric.shim.Chaincode;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.hyperledger.fabric.shim.ledger.CompositeKey;\nimport org.hyperledger.fabric.shim.ledger.KeyModification;\nimport org.hyperledger.fabric.shim.ledger.KeyValue;\nimport org.hyperledger.fabric.shim.ledger.QueryResultsIterator;\nimport org.hyperledger.fabric.shim.ledger.QueryResultsIteratorWithMetadata;\n\npublic final class ChaincodeStubNaiveImpl implements ChaincodeStub {\n    private List<String> args;\n    private List<byte[]> argsAsByte;\n    private final Map<String, ByteString> state;\n    private final Chaincode.Response resp;\n    private String certificate = TestUtil.CERT_WITHOUT_ATTRS;\n\n    public ChaincodeStubNaiveImpl() {\n        args = new ArrayList<>();\n        args.add(\"func1\");\n        args.add(\"param1\");\n        args.add(\"param2\");\n\n        state = new HashMap<>();\n        state.put(\"a\", ByteString.copyFrom(\"asdf\", StandardCharsets.UTF_8));\n\n        argsAsByte = null;\n\n        resp = new Chaincode.Response(404, \"Wrong cc name\", new byte[] {});\n    }\n\n    ChaincodeStubNaiveImpl(final List<String> args) {\n        this.args = args;\n        state = new HashMap<>();\n        state.put(\"a\", ByteString.copyFrom(\"asdf\", StandardCharsets.UTF_8));\n\n        argsAsByte = null;\n\n        resp = new Chaincode.Response(404, \"Wrong cc name\", new byte[] {});\n    }\n\n    @Override\n    public List<byte[]> getArgs() {\n        if (argsAsByte == null) {\n            argsAsByte = args.stream()\n                    .map(arg -> arg.getBytes(StandardCharsets.UTF_8))\n                    .collect(Collectors.toList());\n        }\n        return argsAsByte;\n    }\n\n    @Override\n    public List<String> getStringArgs() {\n        return args;\n    }\n\n    @Override\n    public String getFunction() {\n        return args.get(0);\n    }\n\n    @Override\n    public List<String> getParameters() {\n        return args.subList(1, args.size());\n    }\n\n    @Override\n    public String getTxId() {\n        return \"tx0\";\n    }\n\n    @Override\n    public String getChannelId() {\n        return \"ch0\";\n    }\n\n    @Override\n    public Chaincode.Response invokeChaincode(\n            final String chaincodeName, final List<byte[]> args, final String channel) {\n        return resp;\n    }\n\n    @Override\n    public byte[] getState(final String key) {\n        return state.get(key).toByteArray();\n    }\n\n    @Override\n    public byte[] getStateValidationParameter(final String key) {\n        return new byte[0];\n    }\n\n    @Override\n    public void putState(final String key, final byte[] value) {\n        state.put(key, ByteString.copyFrom(value));\n    }\n\n    @Override\n    public void setStateValidationParameter(final String key, final byte[] value) {}\n\n    @Override\n    public void delState(final String key) {\n        state.remove(key);\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getStateByRange(final String startKey, final String endKey) {\n        return null;\n    }\n\n    @Override\n    public QueryResultsIteratorWithMetadata<KeyValue> getStateByRangeWithPagination(\n            final String startKey, final String endKey, final int pageSize, final String bookmark) {\n        return null;\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(final String compositeKey) {\n        return null;\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(\n            final String objectType, final String... attributes) {\n        return null;\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(final CompositeKey compositeKey) {\n        return null;\n    }\n\n    @Override\n    public QueryResultsIteratorWithMetadata<KeyValue> getStateByPartialCompositeKeyWithPagination(\n            final CompositeKey compositeKey, final int pageSize, final String bookmark) {\n        return null;\n    }\n\n    @Override\n    public CompositeKey createCompositeKey(final String objectType, final String... attributes) {\n        return null;\n    }\n\n    @Override\n    public CompositeKey splitCompositeKey(final String compositeKey) {\n        return null;\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getQueryResult(final String query) {\n        return null;\n    }\n\n    @Override\n    public QueryResultsIteratorWithMetadata<KeyValue> getQueryResultWithPagination(\n            final String query, final int pageSize, final String bookmark) {\n        return null;\n    }\n\n    @Override\n    public QueryResultsIterator<KeyModification> getHistoryForKey(final String key) {\n        return null;\n    }\n\n    @Override\n    public byte[] getPrivateData(final String collection, final String key) {\n        return new byte[0];\n    }\n\n    @Override\n    public byte[] getPrivateDataHash(final String collection, final String key) {\n        return new byte[0];\n    }\n\n    @Override\n    public byte[] getPrivateDataValidationParameter(final String collection, final String key) {\n        return new byte[0];\n    }\n\n    @Override\n    public void putPrivateData(final String collection, final String key, final byte[] value) {}\n\n    @Override\n    public void setPrivateDataValidationParameter(final String collection, final String key, final byte[] value) {}\n\n    @Override\n    public void delPrivateData(final String collection, final String key) {}\n\n    @Override\n    public void purgePrivateData(final String collection, final String key) {}\n\n    @Override\n    public QueryResultsIterator<KeyValue> getPrivateDataByRange(\n            final String collection, final String startKey, final String endKey) {\n        return null;\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(\n            final String collection, final String compositeKey) {\n        return null;\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(\n            final String collection, final CompositeKey compositeKey) {\n        return null;\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(\n            final String collection, final String objectType, final String... attributes) {\n        return null;\n    }\n\n    @Override\n    public QueryResultsIterator<KeyValue> getPrivateDataQueryResult(final String collection, final String query) {\n        return null;\n    }\n\n    @Override\n    public void setEvent(final String name, final byte[] payload) {}\n\n    @Override\n    public ChaincodeEvent getEvent() {\n        return null;\n    }\n\n    @Override\n    public SignedProposal getSignedProposal() {\n        return null;\n    }\n\n    @Override\n    public Instant getTxTimestamp() {\n        return null;\n    }\n\n    @Override\n    public byte[] getCreator() {\n        return buildSerializedIdentity();\n    }\n\n    @Override\n    public Map<String, byte[]> getTransient() {\n        return new HashMap<>();\n    }\n\n    @Override\n    public byte[] getBinding() {\n        return new byte[0];\n    }\n\n    void setStringArgs(final List<String> args) {\n        this.args = args;\n        this.argsAsByte = args.stream().map(String::getBytes).collect(Collectors.toList());\n    }\n\n    public byte[] buildSerializedIdentity() {\n        final SerializedIdentity.Builder identity = SerializedIdentity.newBuilder();\n        identity.setMspid(\"testMSPID\");\n        final byte[] decodedCert = Base64.getDecoder().decode(this.certificate);\n        identity.setIdBytes(ByteString.copyFrom(decodedCert));\n        final SerializedIdentity builtIdentity = identity.build();\n        return builtIdentity.toByteArray();\n    }\n\n    // Used by tests to control which serialized identity is returned by\n    // buildSerializedIdentity\n    public void setCertificate(final String certificateToTest) {\n        this.certificate = certificateToTest;\n    }\n\n    @Override\n    public String getMspId() {\n        return \"fakemspid\";\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/ClientIdentityTest.java",
    "content": "/*\n * Copyright 2019 IBM DTCC All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract;\n\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nimport java.math.BigInteger;\nimport org.hyperledger.fabric.TestUtil;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.junit.jupiter.api.Test;\n\nfinal class ClientIdentityTest {\n    /** Test client identity can be created using certificate without attributes */\n    @Test\n    void clientIdentityWithoutAttributes() throws Exception {\n        final ChaincodeStub stub = new ChaincodeStubNaiveImpl();\n        final ClientIdentity identity = new ClientIdentity(stub);\n        assertEquals(identity.getMSPID(), \"testMSPID\");\n        assertEquals(\n                identity.getId(),\n                \"x509::CN=admin, OU=Fabric, O=Hyperledger, ST=North Carolina, C=US::CN=example.com,\"\n                        + \" OU=WWW, O=Internet Widgets, L=San Francisco, ST=California, C=US\");\n        assertEquals(identity.getAttributeValue(\"attr1\"), null);\n        assertEquals(identity.getAttributeValue(\"val1\"), null);\n        assertEquals(\n                identity.getX509Certificate().getSubjectX500Principal().toString(),\n                \"CN=admin, OU=Fabric, O=Hyperledger, ST=North Carolina, C=US\");\n        assertEquals(\n                identity.getX509Certificate().getSerialNumber(),\n                new BigInteger(\"689287698446788666856807436918134903862142510628\"));\n    }\n\n    /** Test client identity can be created using certificate with attributes */\n    @Test\n    void clientIdentityWithAttributes() throws Exception {\n        final ChaincodeStub stub = new ChaincodeStubNaiveImpl();\n        ((ChaincodeStubNaiveImpl) stub).setCertificate(TestUtil.CERT_WITH_ATTRS);\n        final ClientIdentity identity = new ClientIdentity(stub);\n        assertEquals(identity.getMSPID(), \"testMSPID\");\n        assertEquals(identity.getId(), \"x509::CN=MyTestUserWithAttrs::CN=fabric-ca-server\");\n        assertEquals(identity.getAttributeValue(\"attr1\"), \"val1\");\n        assertEquals(identity.getAttributeValue(\"val1\"), null);\n        assertEquals(identity.assertAttributeValue(\"attr1\", \"val1\"), true);\n        assertEquals(identity.assertAttributeValue(\"attr1\", \"val2\"), false);\n        assertEquals(identity.assertAttributeValue(\"attr2\", \"val1\"), false);\n        assertEquals(identity.getX509Certificate().getSubjectX500Principal().toString(), \"CN=MyTestUserWithAttrs\");\n        assertEquals(\n                identity.getX509Certificate().getSerialNumber(),\n                new BigInteger(\"172910998202207082780622887076293058980152824437\"));\n    }\n\n    /** Test client identity can be created using certificate with multiple attributes */\n    @Test\n    void clientIdentityWithMultipleAttributes() throws Exception {\n        final ChaincodeStub stub = new ChaincodeStubNaiveImpl();\n        ((ChaincodeStubNaiveImpl) stub).setCertificate(TestUtil.CERT_MULTIPLE_ATTRIBUTES);\n        final ClientIdentity identity = new ClientIdentity(stub);\n        assertEquals(identity.getMSPID(), \"testMSPID\");\n        assertEquals(\n                identity.getId(),\n                \"x509::CN=test, OU=client::CN=ca.org1.example.com, O=org1.example.com, L=San Francisco, ST=California, C=US\");\n        assertEquals(identity.getAttributeValue(\"hello\"), \"world\");\n        assertEquals(identity.getAttributeValue(\"foo\"), \"bar\");\n        assertEquals(identity.getAttributeValue(\"attr1\"), \"val1\");\n        assertEquals(identity.getAttributeValue(\"val1\"), null);\n        assertEquals(identity.assertAttributeValue(\"hello\", \"world\"), true);\n        assertEquals(identity.assertAttributeValue(\"attr1\", \"val2\"), false);\n        assertEquals(identity.assertAttributeValue(\"hello\", \"val1\"), false);\n        assertEquals(identity.getX509Certificate().getSubjectX500Principal().toString(), \"CN=test, OU=client\");\n        assertEquals(\n                identity.getX509Certificate().getSerialNumber(),\n                new BigInteger(\"400549269877250942864348502164024974865235124098\"));\n    }\n\n    /** Test client identity can be created using certificate with long distinguished name */\n    @Test\n    void clientIdentityWithLongDNs() throws Exception {\n        final ChaincodeStub stub = new ChaincodeStubNaiveImpl();\n        ((ChaincodeStubNaiveImpl) stub).setCertificate(TestUtil.CERT_WITH_DNS);\n        final ClientIdentity identity = new ClientIdentity(stub);\n        assertEquals(identity.getMSPID(), \"testMSPID\");\n        assertEquals(\n                identity.getId(),\n                \"x509::CN=User1@org2.example.com, L=San Francisco, ST=California,\"\n                        + \" C=US::CN=ca.org2.example.com, O=org2.example.com, L=San Francisco, ST=California, C=US\");\n        assertEquals(\n                identity.getX509Certificate().getSubjectX500Principal().toString(),\n                \"CN=User1@org2.example.com, L=San Francisco, ST=California, C=US\");\n        assertEquals(\n                identity.getX509Certificate().getSerialNumber(),\n                new BigInteger(\"175217963267961225716341475631843075227\"));\n    }\n\n    /** Test client identity throws a ContractRuntimeException when creating a serialized identity fails */\n    @Test\n    void catchInvalidProtocolBufferException() {\n        final ChaincodeStub stub = mock(ChaincodeStub.class);\n        when(stub.getCreator()).thenReturn(\"somethingInvalid\".getBytes());\n\n        assertThatThrownBy(() -> ContextFactory.getInstance().createContext(stub))\n                .isInstanceOf(ContractRuntimeException.class)\n                .hasMessage(\"Could not create new client identity\");\n    }\n\n    /** Test client identity attributes are empty when using a certificate with dummy attributes */\n    @Test\n    void createClientIdentityWithDummyAttributesCert() throws Exception {\n        final ChaincodeStub stub = new ChaincodeStubNaiveImpl();\n        // Create a certificate with rubbish attributes\n        final String certWithDummyAttrs =\n                TestUtil.createCertWithIdentityAttributes(\"{gsdhrlxhvcilgwoueglfs,djhzxo;vjs.dcx }\");\n        ((ChaincodeStubNaiveImpl) stub).setCertificate(certWithDummyAttrs);\n        final ClientIdentity identity = new ClientIdentity(stub);\n\n        assertEquals(identity.getMSPID(), \"testMSPID\");\n        assertEquals(identity.getAttributeValue(\"attr1\"), null);\n        assertEquals(identity.getAttributeValue(\"val1\"), null);\n        assertEquals(identity.getX509Certificate().getSubjectX500Principal().toString(), \"CN=test, OU=client\");\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/ContextFactoryTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.hamcrest.Matchers.is;\nimport static org.hamcrest.Matchers.sameInstance;\n\nimport java.util.Collections;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.junit.jupiter.api.Test;\n\nfinal class ContextFactoryTest {\n\n    @Test\n    void getInstance() {\n        final ContextFactory f1 = ContextFactory.getInstance();\n        final ContextFactory f2 = ContextFactory.getInstance();\n        assertThat(f1, sameInstance(f2));\n    }\n\n    @Test\n    void createContext() {\n        final ChaincodeStub stub = new ChaincodeStubNaiveImpl();\n        final Context ctx = ContextFactory.getInstance().createContext(stub);\n\n        assertThat(stub.getArgs(), is(equalTo(ctx.getStub().getArgs())));\n        assertThat(stub.getStringArgs(), is(equalTo(ctx.getStub().getStringArgs())));\n        assertThat(stub.getFunction(), is(equalTo(ctx.getStub().getFunction())));\n        assertThat(stub.getParameters(), is(equalTo(ctx.getStub().getParameters())));\n        assertThat(stub.getTxId(), is(equalTo(ctx.getStub().getTxId())));\n        assertThat(stub.getChannelId(), is(equalTo(ctx.getStub().getChannelId())));\n        assertThat(\n                stub.invokeChaincode(\"cc\", Collections.emptyList(), \"ch0\"),\n                is(equalTo(ctx.getStub().invokeChaincode(\"cc\", Collections.emptyList(), \"ch0\"))));\n\n        assertThat(stub.getState(\"a\"), is(equalTo(ctx.getStub().getState(\"a\"))));\n        ctx.getStub().putState(\"b\", \"sdfg\".getBytes());\n        assertThat(stub.getStringState(\"b\"), is(equalTo(ctx.getStub().getStringState(\"b\"))));\n\n        assertThat(ctx.clientIdentity.getMSPID(), is(equalTo(\"testMSPID\")));\n        assertThat(\n                ctx.clientIdentity.getId(),\n                is(equalTo(\"x509::CN=admin, OU=Fabric, O=Hyperledger, ST=North Carolina,\"\n                        + \" C=US::CN=example.com, OU=WWW, O=Internet Widgets, L=San Francisco, ST=California, C=US\")));\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/ContextTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.sameInstance;\n\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.junit.jupiter.api.Test;\n\nfinal class ContextTest {\n\n    /** Test creating a new context returns what we expect */\n    @Test\n    void getInstance() {\n        final ChaincodeStub stub = new ChaincodeStubNaiveImpl();\n        final Context context1 = new Context(stub);\n        final Context context2 = new Context(stub);\n        assertThat(context1.getStub(), sameInstance(context2.getStub()));\n    }\n\n    /** Test identity created in Context constructor matches getClientIdentity */\n    @Test\n    void getSetClientIdentity() {\n        final ChaincodeStub stub = new ChaincodeStubNaiveImpl();\n        final Context context = ContextFactory.getInstance().createContext(stub);\n        assertThat(context.getClientIdentity(), sameInstance(context.clientIdentity));\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/ContractInterfaceTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract;\n\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.instanceOf;\nimport static org.hamcrest.Matchers.is;\n\nimport org.hyperledger.fabric.shim.ChaincodeException;\nimport org.junit.jupiter.api.Test;\n\nfinal class ContractInterfaceTest {\n    @Test\n    void createContext() {\n        assertThat(\n                new ContractInterface() {}.createContext(new ChaincodeStubNaiveImpl()), is(instanceOf(Context.class)));\n    }\n\n    @Test\n    void unknownTransaction() {\n        final ContractInterface c = new ContractInterface() {};\n\n        assertThatThrownBy(() -> c.unknownTransaction(c.createContext(new ChaincodeStubNaiveImpl())))\n                .isInstanceOf(ChaincodeException.class)\n                .hasMessage(\"Undefined contract method called\");\n    }\n\n    @Test\n    void beforeTransaction() {\n        final ContractInterface c = new ContractInterface() {};\n\n        c.beforeTransaction(c.createContext(new ChaincodeStubNaiveImpl()));\n    }\n\n    @Test\n    void afterTransaction() {\n        final ContractInterface c = new ContractInterface() {};\n        c.afterTransaction(c.createContext(new ChaincodeStubNaiveImpl()), \"ReturnValue\");\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/ContractRouterTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract;\n\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.contains;\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.hamcrest.Matchers.is;\nimport static org.hamcrest.Matchers.notNullValue;\nimport static org.hamcrest.Matchers.nullValue;\n\nimport contract.SampleContract;\nimport java.io.IOException;\nimport java.net.InetSocketAddress;\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.execution.ExecutionFactory;\nimport org.hyperledger.fabric.contract.execution.InvocationRequest;\nimport org.hyperledger.fabric.shim.Chaincode;\nimport org.hyperledger.fabric.shim.ChaincodeServer;\nimport org.hyperledger.fabric.shim.ChaincodeServerProperties;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.hyperledger.fabric.shim.NettyChaincodeServer;\nimport org.junit.jupiter.api.Test;\n\nfinal class ContractRouterTest {\n    @Test\n    void testCreateFailsWithoutValidOptions() {\n        assertThatThrownBy(() -> new ContractRouter(new String[] {}))\n                .isInstanceOf(IllegalArgumentException.class)\n                .hasMessageContaining(\"The chaincode id must be specified using either the -i or --i command \"\n                        + \"line options or the CORE_CHAINCODE_ID_NAME environment variable.\");\n    }\n\n    @Test\n    void testCreateAndScan() {\n        final ContractRouter r = new ContractRouter(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        r.findAllContracts();\n        final ChaincodeStub s = new ChaincodeStubNaiveImpl();\n\n        // Test Transaction routing\n        final List<String> args = new ArrayList<>();\n        args.add(\"samplecontract:t1\");\n        args.add(\"asdf\");\n        ((ChaincodeStubNaiveImpl) s).setStringArgs(args);\n        final InvocationRequest request = ExecutionFactory.getInstance().createRequest(s);\n        assertThat(\n                request.getNamespace(),\n                is(equalTo(SampleContract.class.getAnnotation(Contract.class).name())));\n        assertThat(request.getMethod(), is(equalTo(\"t1\")));\n        assertThat(request.getRequestName(), is(equalTo(\"samplecontract:t1\")));\n        assertThat(request.getArgs(), is(contains(s.getArgs().get(1))));\n    }\n\n    @Test\n    void testInit() {\n        final ContractRouter r = new ContractRouter(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        r.findAllContracts();\n        final ChaincodeStub s = new ChaincodeStubNaiveImpl();\n\n        final List<String> args = new ArrayList<>();\n        args.add(\"samplecontract:t1\");\n        args.add(\"asdf\");\n        ((ChaincodeStubNaiveImpl) s).setStringArgs(args);\n\n        SampleContract.setBeforeInvoked(0);\n        SampleContract.setAfterInvoked(0);\n        SampleContract.setDoWorkInvoked(0);\n        SampleContract.setT1Invoked(0);\n\n        final Chaincode.Response response = r.init(s);\n        assertThat(response, is(notNullValue()));\n        assertThat(response.getStatus(), is(Chaincode.Response.Status.SUCCESS));\n        assertThat(response.getMessage(), is(nullValue()));\n        assertThat(response.getStringPayload(), is(equalTo(\"asdf\")));\n        assertThat(SampleContract.getBeforeInvoked(), is(1));\n        assertThat(SampleContract.getAfterInvoked(), is(1));\n        assertThat(SampleContract.getDoWorkInvoked(), is(1));\n        assertThat(SampleContract.getT1Invoked(), is(1));\n    }\n\n    /** Test invoking two transaction functions in a contract via fully qualified name */\n    @Test\n    void testInvokeTwoTxnsThatExist() {\n        final ContractRouter r = new ContractRouter(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        r.findAllContracts();\n        final ChaincodeStub s = new ChaincodeStubNaiveImpl();\n\n        final List<String> args = new ArrayList<>();\n        args.add(\"samplecontract:t1\");\n        args.add(\"asdf\");\n        ((ChaincodeStubNaiveImpl) s).setStringArgs(args);\n\n        SampleContract.setBeforeInvoked(0);\n        SampleContract.setAfterInvoked(0);\n        SampleContract.setDoWorkInvoked(0);\n        SampleContract.setT1Invoked(0);\n\n        final Chaincode.Response response = r.invoke(s);\n        assertThat(response, is(notNullValue()));\n        assertThat(response.getStatus(), is(Chaincode.Response.Status.SUCCESS));\n        assertThat(response.getMessage(), is(nullValue()));\n        assertThat(response.getStringPayload(), is(equalTo(\"asdf\")));\n        assertThat(SampleContract.getBeforeInvoked(), is(1));\n        assertThat(SampleContract.getAfterInvoked(), is(1));\n        assertThat(SampleContract.getDoWorkInvoked(), is(1));\n        assertThat(SampleContract.getT1Invoked(), is(1));\n\n        args.clear();\n        args.add(\"samplecontract:t5\");\n        args.add(\"asdf\");\n        ((ChaincodeStubNaiveImpl) s).setStringArgs(args);\n\n        SampleContract.setBeforeInvoked(0);\n        SampleContract.setAfterInvoked(0);\n        SampleContract.setDoWorkInvoked(0);\n        SampleContract.setT1Invoked(0);\n\n        final Chaincode.Response secondResponse = r.invoke(s);\n        assertThat(secondResponse, is(notNullValue()));\n        assertThat(secondResponse.getStatus(), is(Chaincode.Response.Status.SUCCESS));\n        assertThat(secondResponse.getMessage(), is(nullValue()));\n        assertThat(secondResponse.getStringPayload(), is(nullValue()));\n        assertThat(SampleContract.getBeforeInvoked(), is(1));\n        assertThat(SampleContract.getAfterInvoked(), is(1));\n        assertThat(SampleContract.getDoWorkInvoked(), is(1));\n        assertThat(SampleContract.getT1Invoked(), is(0));\n    }\n\n    @Test\n    void testInvokeTxnWithDefinedName() {\n        final ContractRouter r = new ContractRouter(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        r.findAllContracts();\n        final ChaincodeStub s = new ChaincodeStubNaiveImpl();\n\n        final List<String> args = new ArrayList<>();\n        args.add(\"samplecontract:t4\");\n        args.add(\"asdf\");\n        ((ChaincodeStubNaiveImpl) s).setStringArgs(args);\n\n        SampleContract.setBeforeInvoked(0);\n        SampleContract.setAfterInvoked(0);\n        SampleContract.setDoWorkInvoked(0);\n        SampleContract.setT1Invoked(0);\n\n        final Chaincode.Response response = r.invoke(s);\n        assertThat(response, is(notNullValue()));\n        assertThat(response.getStatus(), is(Chaincode.Response.Status.SUCCESS));\n        assertThat(response.getMessage(), is(nullValue()));\n        assertThat(response.getStringPayload(), is(equalTo(\"Transaction 4\")));\n        assertThat(SampleContract.getBeforeInvoked(), is(1));\n        assertThat(SampleContract.getAfterInvoked(), is(1));\n        assertThat(SampleContract.getDoWorkInvoked(), is(0));\n        assertThat(SampleContract.getT1Invoked(), is(0));\n    }\n\n    /** Test invoking two transaction functions in a contract via default name name */\n    @Test\n    void testInvokeTwoTxnsWithDefaultNamespace() {\n        final ContractRouter r = new ContractRouter(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        r.findAllContracts();\n        final ChaincodeStub s = new ChaincodeStubNaiveImpl();\n\n        final List<String> args = new ArrayList<>();\n        args.add(\"t1\");\n        args.add(\"asdf\");\n        ((ChaincodeStubNaiveImpl) s).setStringArgs(args);\n\n        SampleContract.setBeforeInvoked(0);\n        SampleContract.setAfterInvoked(0);\n        SampleContract.setDoWorkInvoked(0);\n        SampleContract.setT1Invoked(0);\n\n        final Chaincode.Response response = r.invoke(s);\n        assertThat(response, is(notNullValue()));\n        assertThat(response.getStatus(), is(Chaincode.Response.Status.SUCCESS));\n        assertThat(response.getMessage(), is(nullValue()));\n        assertThat(response.getStringPayload(), is(equalTo(\"asdf\")));\n        assertThat(SampleContract.getBeforeInvoked(), is(1));\n        assertThat(SampleContract.getAfterInvoked(), is(1));\n        assertThat(SampleContract.getDoWorkInvoked(), is(1));\n        assertThat(SampleContract.getT1Invoked(), is(1));\n\n        args.clear();\n        args.add(\"t5\");\n        args.add(\"asdf\");\n        ((ChaincodeStubNaiveImpl) s).setStringArgs(args);\n\n        SampleContract.setBeforeInvoked(0);\n        SampleContract.setAfterInvoked(0);\n        SampleContract.setDoWorkInvoked(0);\n        SampleContract.setT1Invoked(0);\n\n        final Chaincode.Response secondResponse = r.invoke(s);\n        assertThat(secondResponse, is(notNullValue()));\n        assertThat(secondResponse.getStatus(), is(Chaincode.Response.Status.SUCCESS));\n        assertThat(secondResponse.getMessage(), is(nullValue()));\n        assertThat(secondResponse.getStringPayload(), is(nullValue()));\n        assertThat(SampleContract.getBeforeInvoked(), is(1));\n        assertThat(SampleContract.getAfterInvoked(), is(1));\n        assertThat(SampleContract.getDoWorkInvoked(), is(1));\n        assertThat(SampleContract.getT1Invoked(), is(0));\n    }\n\n    @Test\n    void testInvokeTxnWithDefinedNameUsingMethodName() {\n        final ContractRouter r = new ContractRouter(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        r.findAllContracts();\n        final ChaincodeStub s = new ChaincodeStubNaiveImpl();\n\n        final List<String> args = new ArrayList<>();\n        args.add(\"samplecontract:tFour\");\n        args.add(\"asdf\");\n        ((ChaincodeStubNaiveImpl) s).setStringArgs(args);\n\n        SampleContract.setBeforeInvoked(0);\n        SampleContract.setAfterInvoked(0);\n        SampleContract.setDoWorkInvoked(0);\n        SampleContract.setT1Invoked(0);\n\n        final Chaincode.Response response = r.invoke(s);\n        assertThat(response, is(notNullValue()));\n        assertThat(response.getStatus(), is(Chaincode.Response.Status.INTERNAL_SERVER_ERROR));\n        assertThat(response.getMessage(), is(equalTo(\"Undefined contract method called\")));\n        assertThat(response.getStringPayload(), is(nullValue()));\n        assertThat(SampleContract.getBeforeInvoked(), is(1));\n        assertThat(SampleContract.getAfterInvoked(), is(0));\n        assertThat(SampleContract.getDoWorkInvoked(), is(0));\n        assertThat(SampleContract.getT1Invoked(), is(0));\n    }\n\n    @Test\n    void testInvokeContractThatDoesNotExist() {\n        final ContractRouter r = new ContractRouter(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        r.findAllContracts();\n        final ChaincodeStub s = new ChaincodeStubNaiveImpl();\n\n        final List<String> args = new ArrayList<>();\n        args.add(\"thereisnocontract:t1\");\n        args.add(\"asdf\");\n        ((ChaincodeStubNaiveImpl) s).setStringArgs(args);\n\n        SampleContract.setBeforeInvoked(0);\n        SampleContract.setAfterInvoked(0);\n        SampleContract.setDoWorkInvoked(0);\n        SampleContract.setT1Invoked(0);\n\n        final Chaincode.Response response = r.invoke(s);\n        assertThat(response, is(notNullValue()));\n        assertThat(response.getStatus(), is(Chaincode.Response.Status.INTERNAL_SERVER_ERROR));\n        assertThat(response.getMessage(), is(equalTo(\"Undefined contract called\")));\n        assertThat(response.getStringPayload(), is(nullValue()));\n        assertThat(SampleContract.getBeforeInvoked(), is(0));\n        assertThat(SampleContract.getAfterInvoked(), is(0));\n        assertThat(SampleContract.getDoWorkInvoked(), is(0));\n        assertThat(SampleContract.getT1Invoked(), is(0));\n    }\n\n    @Test\n    void testInvokeTxnThatDoesNotExist() {\n        final ContractRouter r = new ContractRouter(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        r.findAllContracts();\n        final ChaincodeStub s = new ChaincodeStubNaiveImpl();\n\n        final List<String> args = new ArrayList<>();\n        args.add(\"samplecontract:notsupposedtoexist\");\n        args.add(\"asdf\");\n        ((ChaincodeStubNaiveImpl) s).setStringArgs(args);\n\n        SampleContract.setBeforeInvoked(0);\n        SampleContract.setAfterInvoked(0);\n        SampleContract.setDoWorkInvoked(0);\n        SampleContract.setT1Invoked(0);\n\n        final Chaincode.Response response = r.invoke(s);\n        assertThat(response, is(notNullValue()));\n        assertThat(response.getStatus(), is(Chaincode.Response.Status.INTERNAL_SERVER_ERROR));\n        assertThat(response.getMessage(), is(equalTo(\"Undefined contract method called\")));\n        assertThat(response.getStringPayload(), is(nullValue()));\n        assertThat(SampleContract.getBeforeInvoked(), is(1));\n        assertThat(SampleContract.getAfterInvoked(), is(0));\n        assertThat(SampleContract.getDoWorkInvoked(), is(0));\n        assertThat(SampleContract.getT1Invoked(), is(0));\n    }\n\n    @Test\n    void testInvokeTxnThatReturnsNullString() {\n        final ContractRouter r = new ContractRouter(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        r.findAllContracts();\n        final ChaincodeStub s = new ChaincodeStubNaiveImpl();\n\n        final List<String> args = new ArrayList<>();\n        args.add(\"samplecontract:t5\");\n        args.add(\"asdf\");\n        ((ChaincodeStubNaiveImpl) s).setStringArgs(args);\n\n        SampleContract.setBeforeInvoked(0);\n        SampleContract.setAfterInvoked(0);\n        SampleContract.setDoWorkInvoked(0);\n        SampleContract.setT1Invoked(0);\n\n        final Chaincode.Response response = r.invoke(s);\n        assertThat(response, is(notNullValue()));\n        assertThat(response.getStatus(), is(Chaincode.Response.Status.SUCCESS));\n        assertThat(response.getMessage(), is(nullValue()));\n        assertThat(response.getStringPayload(), is(nullValue()));\n        assertThat(SampleContract.getBeforeInvoked(), is(1));\n        assertThat(SampleContract.getAfterInvoked(), is(1));\n        assertThat(SampleContract.getDoWorkInvoked(), is(1));\n        assertThat(SampleContract.getT1Invoked(), is(0));\n    }\n\n    @Test\n    void testInvokeTxnThatThrowsAnException() {\n        final ContractRouter r = new ContractRouter(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        r.findAllContracts();\n        final ChaincodeStub s = new ChaincodeStubNaiveImpl();\n\n        final List<String> args = new ArrayList<>();\n        args.add(\"samplecontract:t3\");\n        args.add(\"RuntimeException\");\n        args.add(\"T3 fail!\");\n        ((ChaincodeStubNaiveImpl) s).setStringArgs(args);\n\n        SampleContract.setBeforeInvoked(0);\n        SampleContract.setAfterInvoked(0);\n        SampleContract.setDoWorkInvoked(0);\n\n        final Chaincode.Response response = r.invoke(s);\n        assertThat(response, is(notNullValue()));\n        assertThat(response.getStatus(), is(Chaincode.Response.Status.INTERNAL_SERVER_ERROR));\n        assertThat(response.getMessage(), is(equalTo(\"Error during contract method execution\")));\n        assertThat(response.getStringPayload(), is(nullValue()));\n        assertThat(SampleContract.getBeforeInvoked(), is(1));\n        assertThat(SampleContract.getAfterInvoked(), is(0));\n        assertThat(SampleContract.getDoWorkInvoked(), is(0));\n    }\n\n    @Test\n    void testInvokeTxnThatThrowsAChaincodeException() {\n        final ContractRouter r = new ContractRouter(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        r.findAllContracts();\n        final ChaincodeStub s = new ChaincodeStubNaiveImpl();\n\n        final List<String> args = new ArrayList<>();\n        args.add(\"samplecontract:t3\");\n        args.add(\"TransactionException\");\n        args.add(\"T3 fail!\");\n        ((ChaincodeStubNaiveImpl) s).setStringArgs(args);\n\n        SampleContract.setBeforeInvoked(0);\n        SampleContract.setAfterInvoked(0);\n        SampleContract.setDoWorkInvoked(0);\n\n        final Chaincode.Response response = r.invoke(s);\n        assertThat(response, is(notNullValue()));\n        assertThat(response.getStatus(), is(Chaincode.Response.Status.INTERNAL_SERVER_ERROR));\n        assertThat(response.getMessage(), is(equalTo(\"T3 fail!\")));\n        assertThat(response.getStringPayload(), is(\"T3ERR1\"));\n        assertThat(SampleContract.getBeforeInvoked(), is(1));\n        assertThat(SampleContract.getAfterInvoked(), is(0));\n        assertThat(SampleContract.getDoWorkInvoked(), is(0));\n    }\n\n    /** Test confirming ContractRuntimeExceptions can be created. */\n    @Test\n    void createContractRuntimeExceptions() {\n        final ContractRuntimeException cre1 = new ContractRuntimeException(\"failure\");\n        new ContractRuntimeException(\"another failure\", cre1);\n        new ContractRuntimeException(new Exception(\"cause\"));\n    }\n\n    @Test\n    void testStartingContractRouterWithStartingAChaincodeServer() throws IOException {\n        ChaincodeServerProperties chaincodeServerProperties = new ChaincodeServerProperties();\n        chaincodeServerProperties.setServerAddress(new InetSocketAddress(\"0.0.0.0\", 9999));\n        final ContractRouter r = new ContractRouter(new String[] {\"-i\", \"testId\"});\n        ChaincodeServer chaincodeServer = new NettyChaincodeServer(r, chaincodeServerProperties);\n\n        new Thread(() -> {\n                    try {\n                        r.startRouterWithChaincodeServer(chaincodeServer);\n                    } catch (IOException | InterruptedException e) {\n                        e.printStackTrace();\n                    }\n                })\n                .start();\n\n        try {\n            Thread.sleep(5000);\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n\n        final ChaincodeStubNaiveImpl s = new ChaincodeStubNaiveImpl();\n\n        final List<String> args = new ArrayList<>();\n        args.add(\"samplecontract:t1\");\n        args.add(\"asdf\");\n        s.setStringArgs(args);\n\n        SampleContract.setBeforeInvoked(0);\n        SampleContract.setAfterInvoked(0);\n        SampleContract.setDoWorkInvoked(0);\n        SampleContract.setT1Invoked(0);\n\n        final Chaincode.Response response = r.init(s);\n        assertThat(response, is(notNullValue()));\n        assertThat(\n                response.getMessage() + \" \" + response.getStringPayload() + response.toString(),\n                response.getStatus(),\n                is(Chaincode.Response.Status.SUCCESS));\n        assertThat(response.getMessage(), is(nullValue()));\n        assertThat(response.getStringPayload(), is(equalTo(\"asdf\")));\n        assertThat(SampleContract.getBeforeInvoked(), is(1));\n        assertThat(SampleContract.getAfterInvoked(), is(1));\n        assertThat(SampleContract.getDoWorkInvoked(), is(1));\n        assertThat(SampleContract.getT1Invoked(), is(1));\n\n        chaincodeServer.stop();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/MyType.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract;\n\nimport org.hyperledger.fabric.contract.annotation.DataType;\nimport org.hyperledger.fabric.contract.annotation.Property;\nimport org.json.JSONPropertyIgnore;\n\n@DataType\npublic final class MyType {\n\n    @Property()\n    private String value;\n\n    private String state = \"\";\n\n    public static final String STARTED = \"STARTED\";\n    public static final String STOPPED = \"STOPPED\";\n\n    public void setState(final String state) {\n        this.state = state;\n    }\n\n    @JSONPropertyIgnore()\n    public boolean isStarted() {\n        return STARTED.equals(state);\n    }\n\n    @JSONPropertyIgnore()\n    public boolean isStopped() {\n        return STOPPED.equals(state);\n    }\n\n    public MyType setValue(final String value) {\n        this.value = value;\n        return this;\n    }\n\n    public String getValue() {\n        return this.value;\n    }\n\n    @Override\n    public String toString() {\n        return \"++++ MyType: \" + value;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/MyType2.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract;\n\nimport org.hyperledger.fabric.contract.annotation.DataType;\nimport org.hyperledger.fabric.contract.annotation.Property;\n\n@DataType\npublic final class MyType2 {\n\n    @Property()\n    private String value;\n\n    @Property(\n            schema = {\n                \"title\",\n                \"MrProperty\",\n                \"Pattern\",\n                \"[a-z]\",\n                \"uniqueItems\",\n                \"false\",\n                \"required\",\n                \"true,false\",\n                \"enum\",\n                \"a,bee,cee,dee\",\n                \"minimum\",\n                \"42\"\n            })\n    private String constrainedValue;\n\n    public MyType2 setValue(final String value) {\n        this.value = value;\n        return this;\n    }\n\n    public String getValue() {\n        return this.value;\n    }\n\n    @Override\n    public String toString() {\n        return \"++++ MyType: \" + value;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/TransactionExceptionTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.is;\nimport static org.hamcrest.Matchers.nullValue;\n\nimport org.hyperledger.fabric.shim.ChaincodeException;\nimport org.junit.jupiter.api.Test;\n\nfinal class TransactionExceptionTest {\n\n    class MyTransactionException extends ChaincodeException {\n\n        private static final long serialVersionUID = 1L;\n\n        private final int errorCode;\n\n        MyTransactionException(final int errorCode) {\n            super(\"MyTransactionException\");\n            this.errorCode = errorCode;\n        }\n\n        @Override\n        public byte[] getPayload() {\n            final String payload = String.format(\"E%03d\", errorCode);\n            return payload.getBytes();\n        }\n    }\n\n    @Test\n    void testNoArgConstructor() {\n        final ChaincodeException e = new ChaincodeException();\n        assertThat(e.getMessage(), is(nullValue()));\n        assertThat(e.getPayload(), is(nullValue()));\n    }\n\n    @Test\n    void testMessageArgConstructor() {\n        final ChaincodeException e = new ChaincodeException(\"Failure\");\n        assertThat(e.getMessage(), is(\"Failure\"));\n        assertThat(e.getPayload(), is(nullValue()));\n    }\n\n    @Test\n    void testCauseArgConstructor() {\n        final ChaincodeException e = new ChaincodeException(new Error(\"Cause\"));\n        assertThat(e.getMessage(), is(\"java.lang.Error: Cause\"));\n        assertThat(e.getPayload(), is(nullValue()));\n        assertThat(e.getCause().getMessage(), is(\"Cause\"));\n    }\n\n    @Test\n    void testMessageAndCauseArgConstructor() {\n        final ChaincodeException e = new ChaincodeException(\"Failure\", new Error(\"Cause\"));\n        assertThat(e.getMessage(), is(\"Failure\"));\n        assertThat(e.getPayload(), is(nullValue()));\n        assertThat(e.getCause().getMessage(), is(\"Cause\"));\n    }\n\n    @Test\n    void testMessageAndPayloadArgConstructor() {\n        final ChaincodeException e = new ChaincodeException(\"Failure\", new byte[] {'P', 'a', 'y', 'l', 'o', 'a', 'd'});\n        assertThat(e.getMessage(), is(\"Failure\"));\n        assertThat(e.getPayload(), is(new byte[] {'P', 'a', 'y', 'l', 'o', 'a', 'd'}));\n    }\n\n    @Test\n    void testMessagePayloadAndCauseArgConstructor() {\n        final ChaincodeException e =\n                new ChaincodeException(\"Failure\", new byte[] {'P', 'a', 'y', 'l', 'o', 'a', 'd'}, new Error(\"Cause\"));\n        assertThat(e.getMessage(), is(\"Failure\"));\n        assertThat(e.getPayload(), is(new byte[] {'P', 'a', 'y', 'l', 'o', 'a', 'd'}));\n        assertThat(e.getCause().getMessage(), is(\"Cause\"));\n    }\n\n    @Test\n    void testMessageAndStringPayloadArgConstructor() {\n        final ChaincodeException e = new ChaincodeException(\"Failure\", \"Payload\");\n        assertThat(e.getMessage(), is(\"Failure\"));\n        assertThat(e.getPayload(), is(new byte[] {'P', 'a', 'y', 'l', 'o', 'a', 'd'}));\n    }\n\n    @Test\n    void testMessageStringPayloadAndCauseArgConstructor() {\n        final ChaincodeException e = new ChaincodeException(\"Failure\", \"Payload\", new Error(\"Cause\"));\n        assertThat(e.getMessage(), is(\"Failure\"));\n        assertThat(e.getPayload(), is(new byte[] {'P', 'a', 'y', 'l', 'o', 'a', 'd'}));\n        assertThat(e.getCause().getMessage(), is(\"Cause\"));\n    }\n\n    @Test\n    void testSubclass() {\n        final ChaincodeException e = new MyTransactionException(1);\n        assertThat(e.getMessage(), is(\"MyTransactionException\"));\n        assertThat(e.getPayload(), is(new byte[] {'E', '0', '0', '1'}));\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/execution/ContractExecutionServiceTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract.execution;\n\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.spy;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\nimport contract.SampleContract;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Parameter;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport org.hyperledger.fabric.contract.ChaincodeStubNaiveImpl;\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.ContractRuntimeException;\nimport org.hyperledger.fabric.contract.annotation.Serializer;\nimport org.hyperledger.fabric.contract.execution.impl.ContractExecutionService;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\nimport org.hyperledger.fabric.contract.routing.ParameterDefinition;\nimport org.hyperledger.fabric.contract.routing.TxFunction;\nimport org.hyperledger.fabric.contract.routing.impl.ParameterDefinitionImpl;\nimport org.hyperledger.fabric.contract.routing.impl.SerializerRegistryImpl;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.junit.jupiter.api.Test;\n\nfinal class ContractExecutionServiceTest {\n    @Test\n    void noReturnValue()\n            throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException,\n                    SecurityException {\n        JSONTransactionSerializer jts = new JSONTransactionSerializer();\n        SerializerRegistryImpl serializerRegistry = spy(new SerializerRegistryImpl());\n        ContractExecutionService ces = new ContractExecutionService(serializerRegistry);\n\n        ContractInterface contract = spy(new SampleContract());\n        TxFunction txFn = mock(TxFunction.class);\n        InvocationRequest req = mock(InvocationRequest.class);\n        TxFunction.Routing routing = mock(TxFunction.Routing.class);\n\n        ChaincodeStub stub = new ChaincodeStubNaiveImpl();\n\n        when(txFn.getRouting()).thenReturn(routing);\n        when(req.getArgs()).thenReturn(new ArrayList<>());\n        when(routing.getMethod())\n                .thenReturn(SampleContract.class.getMethod(\"noReturn\", new Class<?>[] {Context.class}));\n        when(routing.getContractInstance()).thenReturn(contract);\n        when(serializerRegistry.getSerializer(any(), any())).thenReturn(jts);\n        ces.executeRequest(txFn, req, stub);\n\n        verify(contract).beforeTransaction(any());\n    }\n\n    @Test()\n    void failureToInvoke()\n            throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException,\n                    SecurityException {\n        JSONTransactionSerializer jts = new JSONTransactionSerializer();\n        SerializerRegistryImpl serializerRegistry = spy(new SerializerRegistryImpl());\n        ContractExecutionService ces = new ContractExecutionService(serializerRegistry);\n\n        spy(new SampleContract());\n        TxFunction txFn = mock(TxFunction.class);\n        InvocationRequest req = mock(InvocationRequest.class);\n        TxFunction.Routing routing = mock(TxFunction.Routing.class);\n\n        ChaincodeStub stub = mock(ChaincodeStub.class);\n\n        when(txFn.getRouting()).thenReturn(routing);\n        when(req.getArgs()).thenReturn(new ArrayList<>() {});\n\n        when(routing.getContractInstance()).thenThrow(IllegalAccessException.class);\n        when(routing.toString()).thenReturn(\"MockMethodName:MockClassName\");\n        when(serializerRegistry.getSerializer(any(), any())).thenReturn(jts);\n\n        assertThatThrownBy(() -> ces.executeRequest(txFn, req, stub))\n                .isInstanceOf(ContractRuntimeException.class)\n                .hasMessage(\"Could not execute contract method: MockMethodName:MockClassName\");\n    }\n\n    @Test()\n    void invokeWithDifferentSerializers()\n            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {\n        JSONTransactionSerializer defaultSerializer = spy(new JSONTransactionSerializer());\n        SerializerInterface customSerializer = mock(SerializerInterface.class);\n        SerializerRegistryImpl serializerRegistry = spy(new SerializerRegistryImpl());\n        ExecutionService executionService = ExecutionFactory.getInstance().createExecutionService(serializerRegistry);\n\n        TxFunction txFn = mock(TxFunction.class);\n        InvocationRequest req = mock(InvocationRequest.class);\n        TxFunction.Routing routing = mock(TxFunction.Routing.class);\n\n        TypeSchema ts = TypeSchema.typeConvert(String.class);\n        Method method = SampleContract.class.getMethod(\"t1\", Context.class, String.class);\n        Parameter[] params = method.getParameters();\n        ParameterDefinition pd = new ParameterDefinitionImpl(\"arg1\", String.class, ts, params[1]);\n\n        byte[] arg = \"asdf\".getBytes();\n        ChaincodeStub stub = new ChaincodeStubNaiveImpl();\n        ContractInterface contract = spy(new SampleContract());\n\n        when(req.getArgs()).thenReturn(Collections.singletonList(arg));\n        when(txFn.getRouting()).thenReturn(routing);\n        when(txFn.getParamsList()).thenReturn(Collections.singletonList(pd));\n        when(txFn.getReturnSchema()).thenReturn(ts);\n        when(routing.getMethod()).thenReturn(method);\n        when(routing.getContractInstance()).thenReturn(contract);\n\n        String defaultSerializerName = defaultSerializer.getClass().getCanonicalName();\n        String customSerializerName = \"customSerializer\";\n\n        // execute transaction with the default serializer\n        when(routing.getSerializerName()).thenReturn(defaultSerializerName);\n        when(serializerRegistry.getSerializer(defaultSerializerName, Serializer.TARGET.TRANSACTION))\n                .thenReturn(defaultSerializer);\n        executionService.executeRequest(txFn, req, stub);\n\n        // execute transaction with the custom serializer\n        when(routing.getSerializerName()).thenReturn(customSerializerName);\n        when(serializerRegistry.getSerializer(customSerializerName, Serializer.TARGET.TRANSACTION))\n                .thenReturn(customSerializer);\n        executionService.executeRequest(txFn, req, stub);\n\n        verify(defaultSerializer).fromBuffer(arg, ts);\n        verify(customSerializer).fromBuffer(arg, ts);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/execution/JSONTransactionSerializerTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.contract.execution;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.nio.charset.StandardCharsets;\nimport org.hyperledger.fabric.contract.AllTypesAsset;\nimport org.hyperledger.fabric.contract.MyType;\nimport org.hyperledger.fabric.contract.metadata.MetadataBuilder;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\nimport org.hyperledger.fabric.contract.routing.TypeRegistry;\nimport org.hyperledger.fabric.contract.routing.impl.TypeRegistryImpl;\nimport org.junit.jupiter.api.DisplayName;\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\n\nfinal class JSONTransactionSerializerTest {\n    @Test\n    void toBuffer() {\n        final TypeRegistry tr = TypeRegistry.getRegistry();\n\n        tr.addDataType(MyType.class);\n\n        MetadataBuilder.addComponent(tr.getDataType(\"MyType\"));\n        final JSONTransactionSerializer serializer = new JSONTransactionSerializer();\n\n        byte[] bytes = serializer.toBuffer(\"hello world\", TypeSchema.typeConvert(String.class));\n        assertThat(new String(bytes, StandardCharsets.UTF_8), equalTo(\"hello world\"));\n\n        bytes = serializer.toBuffer(42, TypeSchema.typeConvert(Integer.class));\n        assertThat(new String(bytes, StandardCharsets.UTF_8), equalTo(\"42\"));\n\n        bytes = serializer.toBuffer(true, TypeSchema.typeConvert(Boolean.class));\n        assertThat(new String(bytes, StandardCharsets.UTF_8), equalTo(\"true\"));\n\n        bytes = serializer.toBuffer(new MyType(), TypeSchema.typeConvert(MyType.class));\n        assertThat(new String(bytes, StandardCharsets.UTF_8), equalTo(\"{}\"));\n\n        bytes = serializer.toBuffer(new MyType().setValue(\"Hello\"), TypeSchema.typeConvert(MyType.class));\n        assertThat(new String(bytes, StandardCharsets.UTF_8), equalTo(\"{\\\"value\\\":\\\"Hello\\\"}\"));\n\n        final MyType[] array = new MyType[2];\n        array[0] = new MyType().setValue(\"hello\");\n        array[1] = new MyType().setValue(\"world\");\n        bytes = serializer.toBuffer(array, TypeSchema.typeConvert(MyType[].class));\n\n        final byte[] buffer = \"[{\\\"value\\\":\\\"hello\\\"},{\\\"value\\\":\\\"world\\\"}]\".getBytes(StandardCharsets.UTF_8);\n\n        assertThat(bytes, equalTo(buffer));\n    }\n\n    @Nested\n    @DisplayName(\"Complex Data types\")\n    final class ComplexDataTypes {\n\n        @Test\n        public void alltypes() {\n            final TypeRegistry tr = TypeRegistry.getRegistry();\n            tr.addDataType(AllTypesAsset.class);\n            tr.addDataType(MyType.class);\n            MetadataBuilder.addComponent(tr.getDataType(\"MyType\"));\n            MetadataBuilder.addComponent(tr.getDataType(\"AllTypesAsset\"));\n\n            final JSONTransactionSerializer serializer = new JSONTransactionSerializer();\n            final AllTypesAsset all = new AllTypesAsset();\n\n            final TypeSchema ts = TypeSchema.typeConvert(AllTypesAsset.class);\n            final byte[] bytes = serializer.toBuffer(all, ts);\n\n            final AllTypesAsset returned = (AllTypesAsset) serializer.fromBuffer(bytes, ts);\n            assertTrue(all.equals(returned));\n        }\n    }\n\n    @Nested\n    @DisplayName(\"Primitive Arrays\")\n    final class PrimitiveArrays {\n        @Test\n        void ints() {\n            final JSONTransactionSerializer serializer = new JSONTransactionSerializer();\n            // convert array of primitive\n            final int[] intarray = new int[] {42, 83};\n            final byte[] bytes = serializer.toBuffer(intarray, TypeSchema.typeConvert(int[].class));\n            assertThat(new String(bytes, StandardCharsets.UTF_8), equalTo(\"[42,83]\"));\n\n            final Object returned = serializer.fromBuffer(bytes, TypeSchema.typeConvert(int[].class));\n            assertThat(returned, equalTo(intarray));\n        }\n\n        @Test\n        void bytes() {\n            final JSONTransactionSerializer serializer = new JSONTransactionSerializer();\n            // convert array of primitive\n            final byte[] array = new byte[] {42, 83};\n            final byte[] bytes = serializer.toBuffer(array, TypeSchema.typeConvert(byte[].class));\n            assertThat(new String(bytes, StandardCharsets.UTF_8), equalTo(\"[42,83]\"));\n\n            final Object returned = serializer.fromBuffer(bytes, TypeSchema.typeConvert(byte[].class));\n            assertThat(returned, equalTo(array));\n        }\n\n        @Test\n        void floats() {\n            final JSONTransactionSerializer serializer = new JSONTransactionSerializer();\n            // convert array of primitive\n            final float[] array = new float[] {42.5F, 83.5F};\n            final byte[] bytes = serializer.toBuffer(array, TypeSchema.typeConvert(float[].class));\n            assertThat(new String(bytes, StandardCharsets.UTF_8), equalTo(\"[42.5,83.5]\"));\n\n            final Object returned = serializer.fromBuffer(bytes, TypeSchema.typeConvert(float[].class));\n            assertThat(returned, equalTo(array));\n        }\n\n        @Test\n        void booleans() {\n            final JSONTransactionSerializer serializer = new JSONTransactionSerializer();\n            // convert array of primitive\n            final boolean[] array = new boolean[] {true, false, true};\n            final byte[] bytes = serializer.toBuffer(array, TypeSchema.typeConvert(boolean[].class));\n            assertThat(new String(bytes, StandardCharsets.UTF_8), equalTo(\"[true,false,true]\"));\n\n            final Object returned = serializer.fromBuffer(bytes, TypeSchema.typeConvert(boolean[].class));\n            assertThat(returned, equalTo(array));\n        }\n\n        @Test\n        void chars() {\n            final JSONTransactionSerializer serializer = new JSONTransactionSerializer();\n            // convert array of primitive\n            final char[] array = new char[] {'a', 'b', 'c'};\n            final byte[] bytes = serializer.toBuffer(array, TypeSchema.typeConvert(char[].class));\n            assertThat(new String(bytes, StandardCharsets.UTF_8), equalTo(\"[\\\"a\\\",\\\"b\\\",\\\"c\\\"]\"));\n\n            final Object returned = serializer.fromBuffer(bytes, TypeSchema.typeConvert(char[].class));\n            assertThat(returned, equalTo(array));\n        }\n    }\n\n    @Nested\n    @DisplayName(\"Nested Arrays\")\n    final class NestedArrays {\n        @Test\n        void ints() {\n            final JSONTransactionSerializer serializer = new JSONTransactionSerializer();\n            final int[][] array = new int[][] {{42, 83}, {83, 42}};\n            final byte[] bytes = serializer.toBuffer(array, TypeSchema.typeConvert(int[][].class));\n            assertThat(new String(bytes, StandardCharsets.UTF_8), equalTo(\"[[42,83],[83,42]]\"));\n\n            final Object returned = serializer.fromBuffer(bytes, TypeSchema.typeConvert(int[][].class));\n            assertThat(returned, equalTo(array));\n        }\n\n        @Test\n        void longs() {\n            final JSONTransactionSerializer serializer = new JSONTransactionSerializer();\n            final long[][] array = new long[][] {{42L, 83L}, {83L, 42L}};\n            final byte[] bytes = serializer.toBuffer(array, TypeSchema.typeConvert(long[][].class));\n            assertThat(new String(bytes, StandardCharsets.UTF_8), equalTo(\"[[42,83],[83,42]]\"));\n\n            final Object returned = serializer.fromBuffer(bytes, TypeSchema.typeConvert(long[][].class));\n            assertThat(returned, equalTo(array));\n        }\n\n        @Test\n        void doubles() {\n            final JSONTransactionSerializer serializer = new JSONTransactionSerializer();\n            final double[][] array = new double[][] {{42.42d, 83.83d}, {83.23d, 42.33d}};\n            final byte[] bytes = serializer.toBuffer(array, TypeSchema.typeConvert(double[][].class));\n            assertThat(new String(bytes, StandardCharsets.UTF_8), equalTo(\"[[42.42,83.83],[83.23,42.33]]\"));\n\n            final Object returned = serializer.fromBuffer(bytes, TypeSchema.typeConvert(double[][].class));\n            assertThat(returned, equalTo(array));\n        }\n\n        @Test\n        void bytes() {\n            final JSONTransactionSerializer serializer = new JSONTransactionSerializer();\n            final byte[][] array = new byte[][] {{42, 83}, {83, 42}};\n            final byte[] bytes = serializer.toBuffer(array, TypeSchema.typeConvert(byte[][].class));\n            assertThat(new String(bytes, StandardCharsets.UTF_8), equalTo(\"[[42,83],[83,42]]\"));\n\n            final Object returned = serializer.fromBuffer(bytes, TypeSchema.typeConvert(byte[][].class));\n            assertThat(returned, equalTo(array));\n        }\n\n        @Test\n        void shorts() {\n            final JSONTransactionSerializer serializer = new JSONTransactionSerializer();\n            final short[][] array = new short[][] {{42, 83}, {83, 42}};\n            final byte[] bytes = serializer.toBuffer(array, TypeSchema.typeConvert(short[][].class));\n            assertThat(new String(bytes, StandardCharsets.UTF_8), equalTo(\"[[42,83],[83,42]]\"));\n\n            final Object returned = serializer.fromBuffer(bytes, TypeSchema.typeConvert(short[][].class));\n            assertThat(returned, equalTo(array));\n        }\n    }\n\n    @Test\n    void fromBufferObject() {\n        final byte[] buffer = \"[{\\\"value\\\":\\\"hello\\\"},{\\\"value\\\":\\\"world\\\"}]\".getBytes(StandardCharsets.UTF_8);\n\n        final TypeRegistry tr = TypeRegistry.getRegistry();\n        tr.addDataType(MyType.class);\n\n        MetadataBuilder.addComponent(tr.getDataType(\"MyType\"));\n\n        final JSONTransactionSerializer serializer = new JSONTransactionSerializer();\n\n        final TypeSchema ts = TypeSchema.typeConvert(MyType[].class);\n        final MyType[] o = (MyType[]) serializer.fromBuffer(buffer, ts);\n        assertThat(o[0].toString(), equalTo(\"++++ MyType: hello\"));\n        assertThat(o[1].toString(), equalTo(\"++++ MyType: world\"));\n    }\n\n    @Test\n    void toBufferPrimitive() {\n        final TypeRegistry tr = TypeRegistry.getRegistry();\n        final JSONTransactionSerializer serializer = new JSONTransactionSerializer();\n\n        TypeSchema ts;\n        Object value;\n        byte[] buffer;\n\n        ts = TypeSchema.typeConvert(boolean.class);\n        value = false;\n        buffer = serializer.toBuffer(value, ts);\n        assertThat(buffer, equalTo(new byte[] {102, 97, 108, 115, 101}));\n        assertThat(serializer.fromBuffer(buffer, ts), equalTo(false));\n\n        ts = TypeSchema.typeConvert(int.class);\n        value = 1;\n        buffer = serializer.toBuffer(value, ts);\n\n        assertThat(buffer, equalTo(new byte[] {49}));\n        assertThat(serializer.fromBuffer(buffer, ts), equalTo(1));\n\n        ts = TypeSchema.typeConvert(long.class);\n        value = 9192631770L;\n        buffer = serializer.toBuffer(value, ts);\n        assertThat(buffer, equalTo(new byte[] {57, 49, 57, 50, 54, 51, 49, 55, 55, 48}));\n        assertThat(serializer.fromBuffer(buffer, ts), equalTo(9192631770L));\n\n        ts = TypeSchema.typeConvert(float.class);\n        final float f = 3.1415927F;\n        buffer = serializer.toBuffer(f, ts);\n        assertThat(buffer, equalTo(new byte[] {51, 46, 49, 52, 49, 53, 57, 50, 55}));\n        assertThat(serializer.fromBuffer(buffer, ts), equalTo(3.1415927F));\n\n        ts = TypeSchema.typeConvert(double.class);\n        final double d = 2.7182818284590452353602874713527;\n        buffer = serializer.toBuffer(d, ts);\n        assertThat(buffer, equalTo(new byte[] {50, 46, 55, 49, 56, 50, 56, 49, 56, 50, 56, 52, 53, 57, 48, 52, 53}));\n        assertThat(serializer.fromBuffer(buffer, ts), equalTo(2.7182818284590452353602874713527));\n    }\n\n    @Test\n    void fromBufferErrors() {\n        final TypeRegistry tr = new TypeRegistryImpl();\n        tr.addDataType(MyType.class);\n        MetadataBuilder.addComponent(tr.getDataType(\"MyType\"));\n        final JSONTransactionSerializer serializer = new JSONTransactionSerializer();\n\n        final TypeSchema ts = TypeSchema.typeConvert(MyType[].class);\n        serializer.toBuffer(null, ts);\n    }\n\n    class MyTestObject {}\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/metadata/MetadataBuilderTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.metadata;\n\nimport contract.SampleContract;\nimport java.io.InputStream;\nimport java.lang.reflect.Field;\nimport java.util.HashMap;\nimport org.everit.json.schema.loader.SchemaClient;\nimport org.everit.json.schema.loader.internal.DefaultSchemaClient;\nimport org.hyperledger.fabric.contract.ChaincodeStubNaiveImpl;\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.routing.ContractDefinition;\nimport org.hyperledger.fabric.contract.routing.impl.ContractDefinitionImpl;\nimport org.hyperledger.fabric.contract.systemcontract.SystemContract;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nfinal class MetadataBuilderTest {\n    // fields are private, so use reflection to bypass this for unit testing\n    private void setMetadataBuilderField(final String name, final Object value)\n            throws NoSuchFieldException, IllegalAccessException {\n        final Field f = MetadataBuilder.class.getDeclaredField(name);\n        f.setAccessible(true);\n        f.set(null, value);\n    }\n\n    @BeforeEach\n    @AfterEach\n    void beforeAndAfterEach() throws NoSuchFieldException, IllegalAccessException {\n\n        setMetadataBuilderField(\"componentMap\", new HashMap<>());\n        setMetadataBuilderField(\"contractMap\", new HashMap<>());\n        setMetadataBuilderField(\"overallInfoMap\", new HashMap<>());\n        setMetadataBuilderField(\"schemaClient\", new DefaultSchemaClient());\n    }\n\n    @Test\n    void systemContract() {\n\n        final SystemContract system = new SystemContract();\n        final ChaincodeStub stub = new ChaincodeStubNaiveImpl();\n        system.getMetadata(new Context(stub));\n    }\n\n    @Test\n    void defaultSchemasNotLoadedFromNetwork() throws NoSuchFieldException, IllegalAccessException {\n        final ContractDefinition contractDefinition = new ContractDefinitionImpl(SampleContract.class);\n        MetadataBuilder.addContract(contractDefinition);\n        setMetadataBuilderField(\"schemaClient\", new SchemaClient() {\n\n            @Override\n            public InputStream get(final String uri) {\n                throw new IllegalStateException(\"Refusing to load schema: \" + uri);\n            }\n        });\n        MetadataBuilder.validate();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/metadata/TypeSchemaTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.metadata;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nimport org.hyperledger.fabric.contract.annotation.DataType;\nimport org.hyperledger.fabric.contract.routing.DataTypeDefinition;\nimport org.hyperledger.fabric.contract.routing.TypeRegistry;\nimport org.hyperledger.fabric.contract.routing.impl.DataTypeDefinitionImpl;\nimport org.hyperledger.fabric.contract.routing.impl.TypeRegistryImpl;\nimport org.json.JSONObject;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nfinal class TypeSchemaTest {\n\n    @BeforeEach\n    void beforeEach() {}\n\n    @Test\n    void putIfNotNull() {\n        final TypeSchema ts = new TypeSchema();\n\n        ts.putIfNotNull(\"Key\", \"value\");\n\n        final String nullstr = null;\n        ts.putIfNotNull(\"Key\", nullstr);\n\n        assertThat(ts.get(\"Key\"), equalTo(\"value\"));\n\n        ts.putIfNotNull(\"Key\", \"\");\n\n        assertThat(ts.get(\"Key\"), equalTo(\"value\"));\n    }\n\n    @Test\n    void getType() {\n        final TypeSchema ts = new TypeSchema();\n        ts.put(\"type\", \"MyType\");\n        assertThat(ts.getType(), equalTo(\"MyType\"));\n\n        final TypeSchema wrapper = new TypeSchema();\n        wrapper.put(\"schema\", ts);\n        assertThat(wrapper.getType(), equalTo(\"MyType\"));\n    }\n\n    @Test\n    void getFormat() {\n        final TypeSchema ts = new TypeSchema();\n        ts.put(\"format\", \"MyFormat\");\n        assertThat(ts.getFormat(), equalTo(\"MyFormat\"));\n\n        final TypeSchema wrapper = new TypeSchema();\n        wrapper.put(\"schema\", ts);\n        assertThat(wrapper.getFormat(), equalTo(\"MyFormat\"));\n    }\n\n    @Test\n    void getRef() {\n        final TypeSchema ts = new TypeSchema();\n        ts.put(\"$ref\", \"#/ref/to/MyType\");\n        assertThat(ts.getRef(), equalTo(\"#/ref/to/MyType\"));\n\n        final TypeSchema wrapper = new TypeSchema();\n        wrapper.put(\"schema\", ts);\n        assertThat(wrapper.getRef(), equalTo(\"#/ref/to/MyType\"));\n    }\n\n    @Test\n    void getItems() {\n        final TypeSchema ts1 = new TypeSchema();\n\n        final TypeSchema ts = new TypeSchema();\n        ts.put(\"items\", ts1);\n        assertThat(ts.getItems(), equalTo(ts1));\n\n        final TypeSchema wrapper = new TypeSchema();\n        wrapper.put(\"schema\", ts);\n        assertThat(wrapper.getItems(), equalTo(ts1));\n    }\n\n    @DataType\n    class MyType {}\n\n    @Test\n    void getTypeClass() {\n        final TypeSchema ts = new TypeSchema();\n\n        ts.put(\"type\", \"string\");\n        final TypeRegistry mockRegistry = new TypeRegistryImpl();\n        assertThat(ts.getTypeClass(mockRegistry), equalTo(String.class));\n\n        ts.put(\"type\", \"integer\");\n        ts.put(\"format\", \"int8\");\n        assertThat(ts.getTypeClass(mockRegistry), equalTo(byte.class));\n\n        ts.put(\"type\", \"integer\");\n        ts.put(\"format\", \"int16\");\n        assertThat(ts.getTypeClass(mockRegistry), equalTo(short.class));\n\n        ts.put(\"type\", \"integer\");\n        ts.put(\"format\", \"int32\");\n        assertThat(ts.getTypeClass(mockRegistry), equalTo(int.class));\n\n        ts.put(\"type\", \"integer\");\n        ts.put(\"format\", \"int64\");\n        assertThat(ts.getTypeClass(mockRegistry), equalTo(long.class));\n\n        ts.put(\"type\", \"number\");\n        ts.put(\"format\", \"double\");\n        assertThat(ts.getTypeClass(mockRegistry), equalTo(double.class));\n\n        ts.put(\"type\", \"number\");\n        ts.put(\"format\", \"float\");\n        assertThat(ts.getTypeClass(mockRegistry), equalTo(float.class));\n\n        ts.put(\"type\", \"boolean\");\n        assertThat(ts.getTypeClass(mockRegistry), equalTo(boolean.class));\n\n        ts.put(\"type\", null);\n        ts.put(\"$ref\", \"#/ref/to/MyType\");\n\n        mockRegistry.addDataType(MyType.class);\n        assertThat(ts.getTypeClass(mockRegistry), equalTo(MyType.class));\n\n        final TypeSchema array = new TypeSchema();\n        array.put(\"type\", \"array\");\n        array.put(\"items\", ts);\n        assertThat(array.getTypeClass(mockRegistry), equalTo(MyType[].class));\n    }\n\n    @Test\n    void unknownConversions() {\n        assertThrows(RuntimeException.class, () -> {\n            final TypeSchema ts = new TypeSchema();\n            final TypeRegistry mockRegistry = new TypeRegistryImpl();\n            ts.put(\"type\", \"integer\");\n            ts.put(\"format\", \"int63\");\n            ts.getTypeClass(mockRegistry);\n        });\n\n        assertThrows(RuntimeException.class, () -> {\n            final TypeSchema ts = new TypeSchema();\n            final TypeRegistry mockRegistry = new TypeRegistryImpl();\n            ts.put(\"type\", \"number\");\n            ts.put(\"format\", \"approximate\");\n            ts.getTypeClass(mockRegistry);\n        });\n    }\n\n    @Test\n    void typeConvertPrimitives() {\n        TypeSchema rts;\n\n        final String[] array = new String[] {};\n        rts = TypeSchema.typeConvert(array.getClass());\n        assertThat(rts.getType(), equalTo(\"array\"));\n\n        rts = TypeSchema.typeConvert(int.class);\n        assertThat(rts.getType(), equalTo(\"integer\"));\n\n        rts = TypeSchema.typeConvert(long.class);\n        assertThat(rts.getType(), equalTo(\"integer\"));\n\n        rts = TypeSchema.typeConvert(float.class);\n        assertThat(rts.getType(), equalTo(\"number\"));\n\n        rts = TypeSchema.typeConvert(double.class);\n        assertThat(rts.getType(), equalTo(\"number\"));\n\n        rts = TypeSchema.typeConvert(byte.class);\n        assertThat(rts.getType(), equalTo(\"integer\"));\n\n        rts = TypeSchema.typeConvert(short.class);\n        assertThat(rts.getType(), equalTo(\"integer\"));\n\n        rts = TypeSchema.typeConvert(boolean.class);\n        assertThat(rts.getType(), equalTo(\"boolean\"));\n    }\n\n    @Test\n    void typeConvertObjects() {\n        TypeSchema rts;\n        rts = TypeSchema.typeConvert(String.class);\n        assertThat(rts.getType(), equalTo(\"string\"));\n\n        final String[] array = new String[] {};\n        rts = TypeSchema.typeConvert(array.getClass());\n        assertThat(rts.getType(), equalTo(\"array\"));\n\n        rts = TypeSchema.typeConvert(Integer.class);\n        assertThat(rts.getType(), equalTo(\"integer\"));\n\n        rts = TypeSchema.typeConvert(Long.class);\n        assertThat(rts.getType(), equalTo(\"integer\"));\n\n        rts = TypeSchema.typeConvert(Float.class);\n        assertThat(rts.getType(), equalTo(\"number\"));\n\n        rts = TypeSchema.typeConvert(Double.class);\n        assertThat(rts.getType(), equalTo(\"number\"));\n\n        rts = TypeSchema.typeConvert(Byte.class);\n        assertThat(rts.getType(), equalTo(\"integer\"));\n\n        rts = TypeSchema.typeConvert(Short.class);\n        assertThat(rts.getType(), equalTo(\"integer\"));\n\n        rts = TypeSchema.typeConvert(Boolean.class);\n        assertThat(rts.getType(), equalTo(\"boolean\"));\n\n        rts = TypeSchema.typeConvert(MyType.class);\n        assertThat(rts.getRef(), equalTo(\"#/components/schemas/TypeSchemaTest$MyType\"));\n    }\n\n    @Test\n    void validate() {\n\n        final TypeSchema ts = TypeSchema.typeConvert(org.hyperledger.fabric.contract.MyType.class);\n        final DataTypeDefinition dtd = new DataTypeDefinitionImpl(org.hyperledger.fabric.contract.MyType.class);\n\n        MetadataBuilder.addComponent(dtd);\n        final JSONObject json = new JSONObject();\n        ts.validate(json);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/routing/ContractDefinitionTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\n\nimport contract.SampleContract;\nimport java.lang.reflect.Method;\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.ContractRuntimeException;\nimport org.hyperledger.fabric.contract.routing.impl.ContractDefinitionImpl;\nimport org.junit.jupiter.api.Test;\n\nfinal class ContractDefinitionTest {\n    @Test\n    void constructor() throws SecurityException {\n\n        final ContractDefinition cf = new ContractDefinitionImpl(SampleContract.class);\n        assertThat(cf.toString()).startsWith(\"samplecontract:\");\n    }\n\n    @Test\n    void duplicateTransaction() throws NoSuchMethodException, SecurityException {\n        final ContractDefinition cf = new ContractDefinitionImpl(SampleContract.class);\n\n        final ContractInterface contract = new SampleContract();\n        final Method m = contract.getClass().getMethod(\"t2\", new Class<?>[] {Context.class});\n\n        cf.addTxFunction(m);\n        assertThatThrownBy(() -> cf.addTxFunction(m))\n                .isInstanceOf(ContractRuntimeException.class)\n                .hasMessage(\"Duplicate transaction method t2\");\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/routing/DataTypeDefinitionTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.entry;\n\nimport java.util.Map;\nimport org.hyperledger.fabric.contract.MyType2;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\nimport org.hyperledger.fabric.contract.routing.impl.DataTypeDefinitionImpl;\nimport org.junit.jupiter.api.Test;\n\nfinal class DataTypeDefinitionTest {\n    @Test\n    void constructor() {\n        final DataTypeDefinitionImpl dtd = new DataTypeDefinitionImpl(MyType2.class);\n        assertThat(dtd.getTypeClass()).isEqualTo(MyType2.class);\n        assertThat(dtd.getName()).isEqualTo(\"org.hyperledger.fabric.contract.MyType2\");\n        assertThat(dtd.getSimpleName()).isEqualTo(\"MyType2\");\n\n        final Map<String, PropertyDefinition> properties = dtd.getProperties();\n        assertThat(properties.size()).isEqualTo(2);\n        assertThat(properties).containsKey(\"value\");\n        assertThat(properties).containsKey(\"constrainedValue\");\n\n        final PropertyDefinition pd = properties.get(\"constrainedValue\");\n        final TypeSchema ts = pd.getSchema();\n\n        assertThat(ts)\n                .contains(\n                        entry(\"title\", \"MrProperty\"),\n                        entry(\"Pattern\", \"[a-z]\"),\n                        entry(\"uniqueItems\", false),\n                        entry(\"required\", new String[] {\"true\", \"false\"}),\n                        entry(\"enum\", new String[] {\"a\", \"bee\", \"cee\", \"dee\"}),\n                        entry(\"minimum\", 42));\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/routing/ParameterDefinitionTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.equalTo;\n\nimport java.lang.reflect.Parameter;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\nimport org.hyperledger.fabric.contract.routing.impl.ParameterDefinitionImpl;\nimport org.junit.jupiter.api.Test;\n\nfinal class ParameterDefinitionTest {\n    @Test\n    void constructor() throws NoSuchMethodException, SecurityException {\n        final Parameter[] params =\n                String.class.getMethod(\"concat\", String.class).getParameters();\n        final ParameterDefinition pd = new ParameterDefinitionImpl(\"test\", String.class, new TypeSchema(), params[0]);\n        assertThat(pd.toString(), equalTo(\"test-class java.lang.String-{}-java.lang.String arg0\"));\n        assertThat(pd.getTypeClass(), equalTo(String.class));\n        assertThat(pd.getParameter(), equalTo(params[0]));\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/routing/PropertyDefinitionTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.equalTo;\n\nimport java.lang.reflect.Field;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\nimport org.hyperledger.fabric.contract.routing.impl.PropertyDefinitionImpl;\nimport org.junit.jupiter.api.Test;\n\nfinal class PropertyDefinitionTest {\n    @Test\n    void constructor() throws NoSuchMethodException, SecurityException {\n        final Field[] props = String.class.getFields();\n        final TypeSchema ts = new TypeSchema();\n        final PropertyDefinition pd = new PropertyDefinitionImpl(\"test\", String.class, ts, props[0]);\n\n        assertThat(pd.getTypeClass(), equalTo(String.class));\n        assertThat(pd.getField(), equalTo(props[0]));\n        assertThat(pd.getSchema(), equalTo(ts));\n        assertThat(pd.getName(), equalTo(\"test\"));\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/routing/TxFunctionTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing;\n\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.startsWith;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\n\nimport org.hyperledger.fabric.contract.Context;\nimport org.hyperledger.fabric.contract.ContractInterface;\nimport org.hyperledger.fabric.contract.ContractRuntimeException;\nimport org.hyperledger.fabric.contract.annotation.Contract;\nimport org.hyperledger.fabric.contract.annotation.Property;\nimport org.hyperledger.fabric.contract.annotation.Transaction;\nimport org.hyperledger.fabric.contract.metadata.TypeSchema;\nimport org.hyperledger.fabric.contract.routing.impl.TxFunctionImpl;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\n\nfinal class TxFunctionTest {\n    @Contract()\n    class TestObject implements ContractInterface {\n\n        @Transaction()\n        public void testMethod1(final Context ctx) {}\n\n        @Transaction()\n        public void testMethod2(final Context ctx, @Property(schema = {\"a\", \"b\"}) final int arg) {}\n\n        @Transaction()\n        public void wibble(final String arg1) {}\n    }\n\n    @Test\n    void constructor() throws NoSuchMethodException, SecurityException {\n        final TestObject test = new TestObject();\n        final ContractDefinition cd = mock(ContractDefinition.class);\n        Mockito.when(cd.getAnnotation()).thenReturn(test.getClass().getAnnotation(Contract.class));\n\n        final TxFunction txfn =\n                new TxFunctionImpl(test.getClass().getMethod(\"testMethod1\", new Class<?>[] {Context.class}), cd);\n        final String name = txfn.getName();\n        assertEquals(name, \"testMethod1\");\n\n        assertThat(txfn.toString(), startsWith(\"testMethod1\"));\n    }\n\n    @Test\n    void property() throws NoSuchMethodException, SecurityException {\n        final TestObject test = new TestObject();\n        final ContractDefinition cd = mock(ContractDefinition.class);\n        Mockito.when(cd.getAnnotation()).thenReturn(test.getClass().getAnnotation(Contract.class));\n        final TxFunction txfn = new TxFunctionImpl(\n                test.getClass().getMethod(\"testMethod2\", new Class<?>[] {Context.class, int.class}), cd);\n        final String name = txfn.getName();\n        assertEquals(name, \"testMethod2\");\n\n        assertThat(txfn.toString(), startsWith(\"testMethod2\"));\n        assertFalse(txfn.isUnknownTx());\n        txfn.setUnknownTx(true);\n        assertTrue(txfn.isUnknownTx());\n\n        final TypeSchema ts = new TypeSchema();\n        txfn.setReturnSchema(ts);\n        final TypeSchema rts = txfn.getReturnSchema();\n        assertEquals(ts, rts);\n    }\n\n    @Test\n    void invaldtxfn() throws NoSuchMethodException, SecurityException {\n        final TestObject test = new TestObject();\n        final ContractDefinition cd = mock(ContractDefinition.class);\n        Mockito.when(cd.getAnnotation()).thenReturn(test.getClass().getAnnotation(Contract.class));\n\n        assertThatThrownBy(() -> new TxFunctionImpl(test.getClass().getMethod(\"wibble\", String.class), cd))\n                .isInstanceOf(ContractRuntimeException.class);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/routing/TypeRegistryTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.routing;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.equalTo;\n\nimport java.util.Collection;\nimport org.hyperledger.fabric.contract.routing.impl.DataTypeDefinitionImpl;\nimport org.hyperledger.fabric.contract.routing.impl.TypeRegistryImpl;\nimport org.junit.jupiter.api.Test;\n\nfinal class TypeRegistryTest {\n    @Test\n    void addDataType() {\n        final TypeRegistryImpl tr = new TypeRegistryImpl();\n        tr.addDataType(String.class);\n\n        final DataTypeDefinition drt = tr.getDataType(\"String\");\n        assertThat(drt.getName(), equalTo(\"java.lang.String\"));\n    }\n\n    @Test\n    void addDataTypeDefinition() {\n        final DataTypeDefinitionImpl dtd = new DataTypeDefinitionImpl(String.class);\n        final TypeRegistryImpl tr = new TypeRegistryImpl();\n        tr.addDataType(dtd);\n\n        final DataTypeDefinition drt = tr.getDataType(\"java.lang.String\");\n        assertThat(drt.getName(), equalTo(\"java.lang.String\"));\n    }\n\n    @Test\n    void getAllDataTypes() {\n\n        final TypeRegistryImpl tr = new TypeRegistryImpl();\n        tr.addDataType(String.class);\n        tr.addDataType(Integer.class);\n        tr.addDataType(Float.class);\n\n        final Collection<DataTypeDefinition> c = tr.getAllDataTypes();\n        assertThat(c.size(), equalTo(3));\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/simplepath/ContractSimplePathTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.contract.simplepath;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.READY;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.REGISTER;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.TRANSACTION;\n\nimport com.google.protobuf.ByteString;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\nimport org.hyperledger.fabric.contract.ContractRouter;\nimport org.hyperledger.fabric.protos.peer.ChaincodeInput;\nimport org.hyperledger.fabric.protos.peer.ChaincodeInput.Builder;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.Response;\nimport org.hyperledger.fabric.shim.mock.peer.ChaincodeMockPeer;\nimport org.hyperledger.fabric.shim.mock.peer.RegisterStep;\nimport org.hyperledger.fabric.shim.mock.peer.ScenarioStep;\nimport org.hyperledger.fabric.shim.utils.MessageUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport uk.org.webcompere.systemstubs.environment.EnvironmentVariables;\nimport uk.org.webcompere.systemstubs.jupiter.SystemStub;\nimport uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension;\n\n@ExtendWith(SystemStubsExtension.class)\nfinal class ContractSimplePathTest {\n    @SystemStub\n    private final EnvironmentVariables environmentVariables = new EnvironmentVariables();\n\n    private ChaincodeMockPeer server;\n\n    @AfterEach\n    void afterTest() throws Exception {\n        if (server != null) {\n            server.stop();\n            server = null;\n        }\n    }\n\n    /**\n     * Test starting the contract logic\n     *\n     * @throws Exception\n     */\n    @Test\n    void testContract() throws Exception {\n\n        final List<ScenarioStep> scenario = new ArrayList<>();\n        scenario.add(new RegisterStep());\n        setLogLevel(\"DEBUG\");\n        server = ChaincodeMockPeer.startServer(scenario);\n        ContractRouter.main(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 1, 5000, TimeUnit.MILLISECONDS);\n\n        assertThat(server.getLastMessageSend().getType()).isEqualTo(READY);\n        assertThat(server.getLastMessageRcvd().getType()).isEqualTo(REGISTER);\n        setLogLevel(\"INFO\");\n    }\n\n    private ChaincodeMessage newInvokeFn(final String[] args) {\n        final Builder invokePayload = ChaincodeInput.newBuilder();\n        for (final String arg : args) {\n            invokePayload.addArgs(ByteString.copyFromUtf8(arg));\n        }\n\n        return MessageUtil.newEventMessage(\n                TRANSACTION, \"testChannel\", \"0\", invokePayload.build().toByteString(), null);\n    }\n\n    private String getLastReturnString() throws Exception {\n        final Response resp = Response.parseFrom(server.getLastMessageRcvd().getPayload());\n        return resp.getPayload().toStringUtf8();\n    }\n\n    private void setLogLevel(final String logLevel) {\n        environmentVariables.set(\"CORE_CHAINCODE_LOGGING_SHIM\", logLevel);\n        environmentVariables.set(\"CORE_CHAINCODE_LOGGING_LEVEL\", logLevel);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/ledger/LedgerTest.java",
    "content": "/*\n * Copyright 2020 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.ledger;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.Mockito.mock;\n\nimport org.hyperledger.fabric.contract.Context;\nimport org.junit.jupiter.api.Test;\n\nfinal class LedgerTest {\n\n    @Test\n    void getLedger() {\n\n        final Context ctx = mock(Context.class);\n        final Ledger ledger = Ledger.getLedger(ctx);\n\n        assertThat(ledger).isNotNull();\n        assertThat(ledger).isInstanceOf(Ledger.class);\n\n        // assert that the ledger instance is new\n        final Ledger ledger2 = Ledger.getLedger(ctx);\n        assertThat(ledger2).isNotSameAs(ledger);\n    }\n\n    @Test\n    void getCollection() {\n\n        final Context ctx = mock(Context.class);\n        final Ledger ledger = Ledger.getLedger(ctx);\n        final Collection collection = ledger.getDefaultCollection();\n        assertThat(collection).isNotNull();\n        assertThat(collection).isInstanceOf(Collection.class);\n\n        collection.placeholder();\n\n        final Collection collection2 = ledger.getDefaultCollection();\n        assertThat(collection2).isNotSameAs(collection);\n    }\n\n    @Test\n    void getNamedCollection() {\n\n        final Context ctx = mock(Context.class);\n        final Ledger ledger = Ledger.getLedger(ctx);\n        final Collection collection = ledger.getCollection(\"myPrivateCollection\");\n        assertThat(collection).isNotNull();\n        assertThat(collection).isInstanceOf(Collection.class);\n\n        final Collection collection2 = ledger.getCollection(\"myPrivateCollection\");\n        assertThat(collection2).isNotSameAs(collection);\n    }\n\n    @Test\n    void getOrganizationCollection() {\n\n        final Context ctx = mock(Context.class);\n        final Ledger ledger = Ledger.getLedger(ctx);\n        final Collection collection = ledger.getOrganizationCollection(\"org1\");\n        assertThat(collection).isNotNull();\n        assertThat(collection).isInstanceOf(Collection.class);\n\n        final Collection collection2 = ledger.getOrganizationCollection(\"org1\");\n        assertThat(collection2).isNotSameAs(collection);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/metrics/MetricsTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.metrics;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.Properties;\nimport org.hyperledger.fabric.metrics.impl.DefaultProvider;\nimport org.hyperledger.fabric.metrics.impl.NullProvider;\nimport org.junit.jupiter.api.DisplayName;\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\n\nfinal class MetricsTest {\n\n    private static final class TestProvider implements MetricsProvider {\n\n        public TestProvider() {}\n\n        @Override\n        public void setTaskMetricsCollector(final TaskMetricsCollector taskService) {}\n\n        @Override\n        public void initialize(final Properties props) {}\n    }\n\n    @Nested\n    @DisplayName(\"Metrics initialize\")\n    final class Initialize {\n\n        @Test\n        void metricsDisabled() {\n            final MetricsProvider provider = Metrics.initialize(new Properties());\n            assertThat(provider).isExactlyInstanceOf(NullProvider.class);\n        }\n\n        @Test\n        void metricsEnabledUnknownProvider() {\n            final Properties props = new Properties();\n            props.put(\"CHAINCODE_METRICS_PROVIDER\", \"org.example.metrics.provider\");\n            props.put(\"CHAINCODE_METRICS_ENABLED\", \"true\");\n\n            assertThrows(\n                    RuntimeException.class,\n                    () -> {\n                        final MetricsProvider provider = Metrics.initialize(props);\n                    },\n                    \"Unable to start metrics\");\n        }\n\n        @Test\n        void metricsNoProvider() {\n            final Properties props = new Properties();\n            props.put(\"CHAINCODE_METRICS_ENABLED\", \"true\");\n\n            final MetricsProvider provider = Metrics.initialize(props);\n            assertTrue(provider instanceof DefaultProvider);\n        }\n\n        @Test\n        void metricsValid() {\n            final Properties props = new Properties();\n            props.put(\"CHAINCODE_METRICS_PROVIDER\", MetricsTest.TestProvider.class.getName());\n            props.put(\"CHAINCODE_METRICS_ENABLED\", \"true\");\n            final MetricsProvider provider = Metrics.initialize(props);\n\n            assertThat(provider).isExactlyInstanceOf(MetricsTest.TestProvider.class);\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/metrics/impl/DefaultProviderTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.metrics.impl;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\nimport java.util.Properties;\nimport java.util.logging.Handler;\nimport java.util.logging.Level;\nimport java.util.logging.LogManager;\nimport java.util.logging.LogRecord;\nimport java.util.logging.Logger;\nimport org.hyperledger.fabric.metrics.TaskMetricsCollector;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.ArgumentCaptor;\nimport org.mockito.Mockito;\n\nfinal class DefaultProviderTest {\n\n    @Test\n    void allMethods() throws InterruptedException {\n        DefaultProvider provider = new DefaultProvider();\n        provider.setTaskMetricsCollector(new TaskMetricsCollector() {\n\n            @Override\n            public int getPoolSize() {\n                return 0;\n            }\n\n            @Override\n            public int getMaximumPoolSize() {\n                return 0;\n            }\n\n            @Override\n            public int getLargestPoolSize() {\n                return 0;\n            }\n\n            @Override\n            public int getCurrentTaskCount() {\n                return 0;\n            }\n\n            @Override\n            public int getCurrentQueueCount() {\n                return 0;\n            }\n\n            @Override\n            public int getCorePoolSize() {\n                return 0;\n            }\n\n            @Override\n            public int getActiveCount() {\n                // TODO Auto-generated method stub\n                return 0;\n            }\n        });\n\n        Logger perfLogger = LogManager.getLogManager().getLogger(\"org.hyperledger.Performance\");\n        Level original = perfLogger.getLevel();\n        try {\n            perfLogger.setLevel(Level.ALL);\n\n            Handler mockHandler = Mockito.mock(Handler.class);\n            ArgumentCaptor<LogRecord> argumentCaptor = ArgumentCaptor.forClass(LogRecord.class);\n            perfLogger.addHandler(mockHandler);\n\n            provider.initialize(new Properties());\n            provider.logMetrics();\n            Thread.sleep(6000);\n            Mockito.verify(mockHandler, Mockito.atLeast(1)).publish(argumentCaptor.capture());\n            LogRecord lr = argumentCaptor.getValue();\n            String msg = lr.getMessage();\n            assertThat(msg)\n                    .contains(\n                            \"{ \\\"active_count\\\":0 , \\\"pool_size\\\":0 , \\\"core_pool_size\\\":0 , \\\"current_task_count\\\":0 , \\\"current_queue_depth\\\":0 \");\n        } finally {\n            perfLogger.setLevel(original);\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/ChaincodeBaseTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatCode;\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\n\nimport io.grpc.ManagedChannelBuilder;\nimport io.grpc.stub.StreamObserver;\nimport java.io.IOException;\nimport java.nio.charset.Charset;\nimport java.util.Properties;\nimport java.util.logging.Handler;\nimport java.util.logging.Level;\nimport java.util.logging.LogRecord;\nimport java.util.logging.Logger;\nimport org.hyperledger.fabric.metrics.Metrics;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.shim.chaincode.EmptyChaincode;\nimport org.hyperledger.fabric.traces.Traces;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Disabled;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.ArgumentCaptor;\nimport org.mockito.Mockito;\nimport uk.org.webcompere.systemstubs.environment.EnvironmentVariables;\nimport uk.org.webcompere.systemstubs.jupiter.SystemStub;\nimport uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension;\n\n@ExtendWith(SystemStubsExtension.class)\nfinal class ChaincodeBaseTest {\n    @SystemStub\n    private final EnvironmentVariables environmentVariables = new EnvironmentVariables();\n\n    @Test\n    void testNewSuccessResponseEmpty() {\n        final org.hyperledger.fabric.shim.Chaincode.Response response = ResponseUtils.newSuccessResponse();\n        assertThat(response.getStatus())\n                .as(\"Response status\")\n                .isEqualTo(org.hyperledger.fabric.shim.Chaincode.Response.Status.SUCCESS);\n        assertThat(response.getMessage()).as(\"Response message\").isNull();\n        assertThat(response.getPayload()).as(\"Response payload\").isNull();\n    }\n\n    @Test\n    void testNewSuccessResponseWithMessage() {\n        final org.hyperledger.fabric.shim.Chaincode.Response response =\n                ResponseUtils.newSuccessResponse(\"Simple message\");\n        assertThat(response.getStatus())\n                .as(\"Response status\")\n                .isEqualTo(org.hyperledger.fabric.shim.Chaincode.Response.Status.SUCCESS);\n        assertThat(response.getMessage()).as(\"Response message\").isEqualTo(\"Simple message\");\n        assertThat(response.getPayload()).as(\"Response payload\").isNull();\n    }\n\n    @Test\n    void testNewSuccessResponseWithPayload() {\n        final org.hyperledger.fabric.shim.Chaincode.Response response =\n                ResponseUtils.newSuccessResponse(\"Simple payload\".getBytes(Charset.defaultCharset()));\n        assertThat(response.getStatus())\n                .as(\"Response status\")\n                .isEqualTo(org.hyperledger.fabric.shim.Chaincode.Response.Status.SUCCESS);\n        assertThat(response.getMessage()).as(\"Response message\").isNull();\n        assertThat(response.getPayload())\n                .as(\"Response payload\")\n                .isEqualTo(\"Simple payload\".getBytes(Charset.defaultCharset()));\n    }\n\n    @Test\n    void testNewSuccessResponseWithMessageAndPayload() {\n        final org.hyperledger.fabric.shim.Chaincode.Response response =\n                ResponseUtils.newSuccessResponse(\"Simple message\", \"Simple payload\".getBytes(Charset.defaultCharset()));\n        assertThat(response.getStatus())\n                .as(\"Response status\")\n                .isEqualTo(org.hyperledger.fabric.shim.Chaincode.Response.Status.SUCCESS);\n        assertThat(response.getMessage()).as(\"Response message\").isEqualTo(\"Simple message\");\n        assertThat(response.getPayload())\n                .as(\"Response payload\")\n                .isEqualTo(\"Simple payload\".getBytes(Charset.defaultCharset()));\n    }\n\n    @Test\n    void testNewErrorResponseEmpty() {\n        final org.hyperledger.fabric.shim.Chaincode.Response response = ResponseUtils.newErrorResponse();\n        assertThat(response.getStatus())\n                .as(\"Response status\")\n                .isEqualTo(org.hyperledger.fabric.shim.Chaincode.Response.Status.INTERNAL_SERVER_ERROR);\n        assertThat(response.getMessage()).as(\"Response message\").isNull();\n        assertThat(response.getPayload()).as(\"Response payload\").isNull();\n    }\n\n    @Test\n    void testNewErrorResponseWithMessage() {\n        final org.hyperledger.fabric.shim.Chaincode.Response response =\n                ResponseUtils.newErrorResponse(\"Simple message\");\n        assertThat(response.getStatus())\n                .as(\"Response status\")\n                .isEqualTo(org.hyperledger.fabric.shim.Chaincode.Response.Status.INTERNAL_SERVER_ERROR);\n        assertThat(response.getMessage()).as(\"Response message\").isEqualTo(\"Simple message\");\n        assertThat(response.getPayload()).as(\"Response payload\").isNull();\n    }\n\n    @Test\n    void testNewErrorResponseWithPayload() {\n        final org.hyperledger.fabric.shim.Chaincode.Response response =\n                ResponseUtils.newErrorResponse(\"Simple payload\".getBytes(Charset.defaultCharset()));\n        assertThat(response.getStatus())\n                .as(\"Response status\")\n                .isEqualTo(org.hyperledger.fabric.shim.Chaincode.Response.Status.INTERNAL_SERVER_ERROR);\n        assertThat(response.getMessage()).as(\"Response message\").isNull();\n        assertThat(response.getPayload())\n                .as(\"Response payload\")\n                .isEqualTo(\"Simple payload\".getBytes(Charset.defaultCharset()));\n    }\n\n    @Test\n    void testNewErrorResponseWithMessageAndPayload() {\n        final org.hyperledger.fabric.shim.Chaincode.Response response =\n                ResponseUtils.newErrorResponse(\"Simple message\", \"Simple payload\".getBytes(Charset.defaultCharset()));\n        assertThat(response.getStatus())\n                .as(\"Response status\")\n                .isEqualTo(org.hyperledger.fabric.shim.Chaincode.Response.Status.INTERNAL_SERVER_ERROR);\n        assertThat(response.getMessage()).as(\"Response message\").isEqualTo(\"Simple message\");\n        assertThat(response.getPayload())\n                .as(\"Response payload\")\n                .isEqualTo(\"Simple payload\".getBytes(Charset.defaultCharset()));\n    }\n\n    @Test\n    void testNewErrorResponseWithException() {\n        final org.hyperledger.fabric.shim.Chaincode.Response response =\n                ResponseUtils.newErrorResponse(new Exception(\"Simple exception\"));\n        assertThat(response.getStatus())\n                .as(\"Response status\")\n                .isEqualTo(org.hyperledger.fabric.shim.Chaincode.Response.Status.INTERNAL_SERVER_ERROR);\n        assertThat(response.getMessage()).as(\"Response message\").isEqualTo(\"Unexpected error\");\n        assertThat(response.getPayload()).as(\"Response payload\").isNull();\n    }\n\n    @Test\n    void testNewErrorResponseWithChaincodeException() {\n        final org.hyperledger.fabric.shim.Chaincode.Response response =\n                ResponseUtils.newErrorResponse(new ChaincodeException(\"Chaincode exception\"));\n        assertThat(response.getStatus())\n                .as(\"Response status\")\n                .isEqualTo(org.hyperledger.fabric.shim.Chaincode.Response.Status.INTERNAL_SERVER_ERROR);\n        assertThat(response.getMessage()).as(\"Response message\").isEqualTo(\"Chaincode exception\");\n        assertThat(response.getPayload()).as(\"Response payload\").isNull();\n    }\n\n    @Test\n    void testOptions() throws Exception {\n        final ChaincodeBase cb = new EmptyChaincode();\n\n        assertThat(cb.getHost()).as(\"Host incorrect\").isEqualTo(ChaincodeBase.DEFAULT_HOST);\n        assertThat(cb.getPort()).as(\"Port incorrect\").isEqualTo(ChaincodeBase.DEFAULT_PORT);\n        assertThat(cb.isTlsEnabled()).as(\"TLS should not be enabled\").isFalse();\n\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"mycc\");\n        environmentVariables.set(\"CORE_PEER_ADDRESS\", \"localhost:7052\");\n        environmentVariables.set(\"CORE_PEER_TLS_ENABLED\", \"true\");\n        environmentVariables.set(\"CORE_TLS_CLIENT_CERT_PATH\", \"non_exist_path3\");\n        environmentVariables.set(\"CORE_TLS_CLIENT_KEY_PATH\", \"non_exist_path2\");\n        environmentVariables.set(\"CORE_PEER_TLS_ROOTCERT_FILE\", \"non_exist_path1\");\n        cb.processEnvironmentOptions();\n        assertThat(cb.getId()).as(\"CCId incorrect\").isEqualTo(\"mycc\");\n        assertThat(cb.getHost()).as(\"Host incorrect\").isEqualTo(\"localhost\");\n        assertThat(cb.getPort()).as(\"Port incorrect\").isEqualTo(7052);\n        assertThat(cb.isTlsEnabled()).as(\"TLS should be enabled\").isTrue();\n        assertThat(cb.getTlsClientRootCertPath()).as(\"Root certificate file\").isEqualTo(\"non_exist_path1\");\n        assertThat(cb.getTlsClientKeyPath()).as(\"Client key file\").isEqualTo(\"non_exist_path2\");\n        assertThat(cb.getTlsClientCertPath()).as(\"Client certificate file\").isEqualTo(\"non_exist_path3\");\n\n        environmentVariables.set(\"CORE_PEER_ADDRESS\", \"localhost1\");\n        cb.processEnvironmentOptions();\n        assertThat(cb.getHost()).as(\"Host incorrect\").isEqualTo(\"localhost\");\n        assertThat(cb.getPort()).as(\"Port incorrect\").isEqualTo(7052);\n\n        assertThatCode(cb::validateOptions).as(\"Wrong arguments\").doesNotThrowAnyException();\n\n        cb.processCommandLineOptions(new String[] {\"-i\", \"mycc1\", \"--peerAddress\", \"localhost.org:7053\"});\n        assertThat(cb.getId()).as(\"CCId incorrect\").isEqualTo(\"mycc1\");\n        assertThat(cb.getHost()).as(\"Host incorrect\").isEqualTo(\"localhost.org\");\n        assertThat(cb.getPort()).as(\"Port incorrect\").isEqualTo(7053);\n\n        assertThatCode(cb::validateOptions).as(\"Wrong arguments\").doesNotThrowAnyException();\n\n        cb.processCommandLineOptions(new String[] {\"-i\", \"mycc1\", \"--peerAddress\", \"localhost1.org.7054\"});\n        assertThat(cb.getHost()).as(\"Host incorrect\").isEqualTo(\"localhost.org\");\n        assertThat(cb.getPort()).as(\"Port incorrect\").isEqualTo(7053);\n    }\n\n    @Test\n    void testUnsetOptionId() {\n        final ChaincodeBase cb = new EmptyChaincode();\n        assertThatThrownBy(cb::validateOptions)\n                .isInstanceOf(IllegalArgumentException.class)\n                .hasMessageContaining(\"The chaincode id must be specified\");\n    }\n\n    @Test\n    void testUnsetOptionClientCertPath() {\n        final ChaincodeBase cb = new EmptyChaincode();\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"mycc\");\n        environmentVariables.set(\"CORE_PEER_TLS_ENABLED\", \"true\");\n        cb.processEnvironmentOptions();\n        assertThatThrownBy(cb::validateOptions)\n                .isInstanceOf(IllegalArgumentException.class)\n                .hasMessageContaining(\"Client key certificate chain\");\n    }\n\n    @Test\n    void testUnsetOptionClientKeyPath() {\n        final ChaincodeBase cb = new EmptyChaincode();\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"mycc\");\n        environmentVariables.set(\"CORE_PEER_TLS_ENABLED\", \"true\");\n        environmentVariables.set(\"CORE_TLS_CLIENT_CERT_PATH\", \"non_exist_path3\");\n        cb.processEnvironmentOptions();\n        assertThatThrownBy(cb::validateOptions)\n                .isInstanceOf(IllegalArgumentException.class)\n                .hasMessageContaining(\"Client key (\");\n    }\n\n    @Test\n    @Disabled\n    void testNewChannelBuilder() throws Exception {\n        final ChaincodeBase cb = new EmptyChaincode();\n\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"mycc\");\n        environmentVariables.set(\"CORE_PEER_ADDRESS\", \"localhost:7052\");\n        environmentVariables.set(\"CORE_PEER_TLS_ENABLED\", \"true\");\n        environmentVariables.set(\"CORE_PEER_TLS_ROOTCERT_FILE\", \"src/test/resources/ca.crt\");\n        environmentVariables.set(\"CORE_TLS_CLIENT_KEY_PATH\", \"src/test/resources/client.key.enc\");\n        environmentVariables.set(\"CORE_TLS_CLIENT_CERT_PATH\", \"src/test/resources/client.crt.enc\");\n\n        cb.processEnvironmentOptions();\n        cb.validateOptions();\n        assertThat(cb.newChannelBuilder()).isInstanceOf(ManagedChannelBuilder.class);\n    }\n\n    @Test\n    void testInitializeLogging() {\n        final ChaincodeBase cb = new EmptyChaincode();\n\n        cb.processEnvironmentOptions();\n        cb.initializeLogging();\n        assertThat(Logger.getLogger(\"org.hyperledger.fabric.shim\").getLevel())\n                .as(\"Wrong log level for org.hyperledger.fabric.shim\")\n                .isEqualTo(Level.INFO);\n        assertThat(Logger.getLogger(cb.getClass().getPackage().getName()).getLevel())\n                .as(\"Wrong log level for \" + cb.getClass().getPackage().getName())\n                .isEqualTo(Level.INFO);\n\n        setLogLevelForChaincode(environmentVariables, cb, \"WRONG\", \"WRONG\");\n        assertThat(Logger.getLogger(\"org.hyperledger.fabric.shim\").getLevel())\n                .as(\"Wrong log level for org.hyperledger.fabric.shim\")\n                .isEqualTo(Level.INFO);\n        assertThat(Logger.getLogger(cb.getClass().getPackage().getName()).getLevel())\n                .as(\"Wrong log level for \" + cb.getClass().getPackage().getName())\n                .isEqualTo(Level.INFO);\n\n        setLogLevelForChaincode(environmentVariables, cb, \"DEBUG\", \"NOTICE\");\n        assertThat(Logger.getLogger(\"org.hyperledger.fabric.shim\").getLevel())\n                .as(\"Wrong log level for org.hyperledger.fabric.shim\")\n                .isEqualTo(Level.FINEST);\n        assertThat(Logger.getLogger(cb.getClass().getPackage().getName()).getLevel())\n                .as(\"Wrong log level for \" + cb.getClass().getPackage().getName())\n                .isEqualTo(Level.CONFIG);\n\n        setLogLevelForChaincode(environmentVariables, cb, \"INFO\", \"WARNING\");\n        assertThat(Logger.getLogger(\"org.hyperledger.fabric.shim\").getLevel())\n                .as(\"Wrong log level for org.hyperledger.fabric.shim\")\n                .isEqualTo(Level.INFO);\n        assertThat(Logger.getLogger(cb.getClass().getPackage().getName()).getLevel())\n                .as(\"Wrong log level for \" + cb.getClass().getPackage().getName())\n                .isEqualTo(Level.WARNING);\n\n        setLogLevelForChaincode(environmentVariables, cb, \"CRITICAL\", \"ERROR\");\n        assertThat(Logger.getLogger(\"org.hyperledger.fabric.shim\").getLevel())\n                .as(\"Wrong log level for org.hyperledger.fabric.shim\")\n                .isEqualTo(Level.SEVERE);\n        assertThat(Logger.getLogger(cb.getClass().getPackage().getName()).getLevel())\n                .as(\"Wrong log level for \" + cb.getClass().getPackage().getName())\n                .isEqualTo(Level.SEVERE);\n    }\n\n    @Test\n    void testStartFailsWithoutValidOptions() {\n        final String[] args = new String[0];\n        final ChaincodeBase cb = new EmptyChaincode();\n\n        Handler mockHandler = Mockito.mock(Handler.class);\n        ArgumentCaptor<LogRecord> argumentCaptor = ArgumentCaptor.forClass(LogRecord.class);\n        Logger logger = Logger.getLogger(\"org.hyperledger.fabric.shim.ChaincodeBase\");\n        logger.addHandler(mockHandler);\n        cb.start(args);\n\n        Mockito.verify(mockHandler, Mockito.atLeast(1)).publish(argumentCaptor.capture());\n        LogRecord lr = argumentCaptor.getValue();\n        String msg = lr.getMessage();\n\n        assertThat(msg).doesNotContain(\"java.lang.NullPointerException\");\n        assertThat(msg)\n                .contains(\n                        \"The chaincode id must be specified using either the -i or --i command line options or the CORE_CHAINCODE_ID_NAME environment variable.\");\n    }\n\n    private static void setLogLevelForChaincode(\n            final EnvironmentVariables environmentVariables,\n            final ChaincodeBase cb,\n            final String shimLevel,\n            final String chaincodeLevel) {\n        environmentVariables.set(ChaincodeBase.CORE_CHAINCODE_LOGGING_SHIM, shimLevel);\n        environmentVariables.set(ChaincodeBase.CORE_CHAINCODE_LOGGING_LEVEL, chaincodeLevel);\n        cb.processEnvironmentOptions();\n        cb.initializeLogging();\n    }\n\n    @Test\n    void connectChaincodeBase() throws IOException {\n        final ChaincodeBase cb = new EmptyChaincode();\n\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"mycc\");\n        environmentVariables.set(\"CORE_PEER_ADDRESS\", \"localhost:7052\");\n        environmentVariables.set(\"CORE_PEER_TLS_ENABLED\", \"false\");\n\n        cb.processEnvironmentOptions();\n        cb.validateOptions();\n\n        final Properties props = cb.getChaincodeConfig();\n        Metrics.initialize(props);\n        Traces.initialize(props);\n\n        cb.connectToPeer(new StreamObserver<>() {\n            @Override\n            public void onNext(final ChaincodeMessage value) {}\n\n            @Override\n            public void onError(final Throwable t) {}\n\n            @Override\n            public void onCompleted() {}\n        });\n\n        environmentVariables.remove(\"CORE_CHAINCODE_ID_NAME\");\n        environmentVariables.remove(\"CORE_PEER_ADDRESS\");\n        environmentVariables.remove(\"CORE_PEER_TLS_ENABLED\");\n    }\n\n    @Test\n    void connectChaincodeBaseNull() {\n        Assertions.assertThrows(IllegalArgumentException.class, () -> {\n            final ChaincodeBase cb = new EmptyChaincode();\n            cb.connectToPeer(null);\n        });\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/ChaincodeServerImplTest.java",
    "content": "/*\n * Copyright 2020 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim;\n\nimport java.io.IOException;\nimport java.net.URISyntaxException;\nimport org.hyperledger.fabric.contract.ContractRouter;\nimport org.hyperledger.fabric.shim.chaincode.EmptyChaincode;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport uk.org.webcompere.systemstubs.environment.EnvironmentVariables;\nimport uk.org.webcompere.systemstubs.jupiter.SystemStub;\nimport uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension;\n\n@ExtendWith(SystemStubsExtension.class)\nfinal class ChaincodeServerImplTest {\n    @SystemStub\n    private final EnvironmentVariables environmentVariables = new EnvironmentVariables();\n\n    @BeforeEach\n    void setEnv() {\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"mycc\");\n        environmentVariables.set(\"CORE_PEER_ADDRESS\", \"localhost:7052\");\n        environmentVariables.set(\"CHAINCODE_SERVER_ADDRESS\", \"0.0.0.0:9999\");\n        environmentVariables.set(\"CORE_PEER_TLS_ENABLED\", \"false\");\n        environmentVariables.set(\"CORE_PEER_TLS_ROOTCERT_FILE\", \"src/test/resources/ca.crt\");\n        environmentVariables.set(\"CORE_TLS_CLIENT_KEY_PATH\", \"src/test/resources/client.key.enc\");\n        environmentVariables.set(\"CORE_TLS_CLIENT_CERT_PATH\", \"src/test/resources/client.crt.enc\");\n    }\n\n    @AfterEach\n    void clearEnv() {\n        environmentVariables.remove(\"CORE_CHAINCODE_ID_NAME\");\n        environmentVariables.remove(\"CORE_PEER_ADDRESS\");\n        environmentVariables.remove(\"CORE_PEER_TLS_ENABLED\");\n        environmentVariables.remove(\"CORE_PEER_TLS_ROOTCERT_FILE\");\n        environmentVariables.remove(\"CORE_TLS_CLIENT_KEY_PATH\");\n        environmentVariables.remove(\"CORE_TLS_CLIENT_CERT_PATH\");\n        environmentVariables.remove(\"CHAINCODE_SERVER_ADDRESS\");\n    }\n\n    @Test\n    void init() {\n        try {\n            final ChaincodeBase chaincodeBase = new EmptyChaincode();\n            ChaincodeServer chaincodeServer =\n                    new NettyChaincodeServer(chaincodeBase, chaincodeBase.getChaincodeServerConfig());\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n    }\n\n    @Test\n    void initEnvNotSet() {\n        clearEnv();\n        try {\n            final ChaincodeBase chaincodeBase = new EmptyChaincode();\n            ChaincodeServer chaincodeServer =\n                    new NettyChaincodeServer(chaincodeBase, chaincodeBase.getChaincodeServerConfig());\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n    }\n\n    @Test\n    void startAndStop() {\n        try {\n            final ChaincodeBase chaincodeBase =\n                    new ContractRouter(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n            ChaincodeServer chaincodeServer =\n                    new NettyChaincodeServer(chaincodeBase, chaincodeBase.getChaincodeServerConfig());\n            new Thread(() -> {\n                        try {\n                            chaincodeServer.start();\n                        } catch (Exception e) {\n                            e.printStackTrace();\n                        }\n                    })\n                    .start();\n            try {\n                Thread.sleep(1000);\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n\n            chaincodeServer.stop();\n        } catch (IOException | URISyntaxException e) {\n            e.printStackTrace();\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/ChaincodeStubTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim;\n\nimport java.time.Instant;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport org.hyperledger.fabric.protos.peer.ChaincodeEvent;\nimport org.hyperledger.fabric.protos.peer.SignedProposal;\nimport org.hyperledger.fabric.shim.Chaincode.Response;\nimport org.hyperledger.fabric.shim.ledger.CompositeKey;\nimport org.hyperledger.fabric.shim.ledger.KeyModification;\nimport org.hyperledger.fabric.shim.ledger.KeyValue;\nimport org.hyperledger.fabric.shim.ledger.QueryResultsIterator;\nimport org.hyperledger.fabric.shim.ledger.QueryResultsIteratorWithMetadata;\nimport org.junit.jupiter.api.Test;\n\nfinal class ChaincodeStubTest {\n\n    @SuppressWarnings(\"PMD.ReturnEmptyCollectionRatherThanNull\")\n    private static final class FakeStub implements ChaincodeStub {\n\n        @Override\n        public List<byte[]> getArgs() {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public List<String> getStringArgs() {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public String getFunction() {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public List<String> getParameters() {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public String getTxId() {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public String getChannelId() {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public Response invokeChaincode(final String chaincodeName, final List<byte[]> args, final String channel) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public byte[] getState(final String key) {\n            return key.getBytes();\n        }\n\n        @Override\n        public byte[] getStateValidationParameter(final String key) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public void putState(final String key, final byte[] value) {\n            // TODO Auto-generated method stub\n\n        }\n\n        @Override\n        public void setStateValidationParameter(final String key, final byte[] value) {\n            // TODO Auto-generated method stub\n\n        }\n\n        @Override\n        public void delState(final String key) {\n            // TODO Auto-generated method stub\n\n        }\n\n        @Override\n        public QueryResultsIterator<KeyValue> getStateByRange(final String startKey, final String endKey) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public QueryResultsIteratorWithMetadata<KeyValue> getStateByRangeWithPagination(\n                final String startKey, final String endKey, final int pageSize, final String bookmark) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(final String compositeKey) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(\n                final String objectType, final String... attributes) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(final CompositeKey compositeKey) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public QueryResultsIteratorWithMetadata<KeyValue> getStateByPartialCompositeKeyWithPagination(\n                final CompositeKey compositeKey, final int pageSize, final String bookmark) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public CompositeKey createCompositeKey(final String objectType, final String... attributes) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public CompositeKey splitCompositeKey(final String compositeKey) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public QueryResultsIterator<KeyValue> getQueryResult(final String query) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public QueryResultsIteratorWithMetadata<KeyValue> getQueryResultWithPagination(\n                final String query, final int pageSize, final String bookmark) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public QueryResultsIterator<KeyModification> getHistoryForKey(final String key) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public byte[] getPrivateData(final String collection, final String key) {\n            return collection.getBytes();\n        }\n\n        @Override\n        public byte[] getPrivateDataHash(final String collection, final String key) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public byte[] getPrivateDataValidationParameter(final String collection, final String key) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public void putPrivateData(final String collection, final String key, final byte[] value) {\n            // TODO Auto-generated method stub\n\n        }\n\n        @Override\n        public void setPrivateDataValidationParameter(final String collection, final String key, final byte[] value) {\n            // TODO Auto-generated method stub\n\n        }\n\n        @Override\n        public void delPrivateData(final String collection, final String key) {\n            // TODO Auto-generated method stub\n\n        }\n\n        @Override\n        public void purgePrivateData(final String collection, final String key) {\n            // TODO Auto-generated method stub\n\n        }\n\n        @Override\n        public QueryResultsIterator<KeyValue> getPrivateDataByRange(\n                final String collection, final String startKey, final String endKey) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(\n                final String collection, final String compositeKey) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(\n                final String collection, final CompositeKey compositeKey) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(\n                final String collection, final String objectType, final String... attributes) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public QueryResultsIterator<KeyValue> getPrivateDataQueryResult(final String collection, final String query) {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public void setEvent(final String name, final byte[] payload) {\n            // TODO Auto-generated method stub\n\n        }\n\n        @Override\n        public ChaincodeEvent getEvent() {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public SignedProposal getSignedProposal() {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public Instant getTxTimestamp() {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public byte[] getCreator() {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public Map<String, byte[]> getTransient() {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public byte[] getBinding() {\n            // TODO Auto-generated method stub\n            return null;\n        }\n\n        @Override\n        public String getMspId() {\n            // TODO Auto-generated method stub\n            return null;\n        }\n    }\n\n    @Test\n    void testDefaultMethods() {\n        final ChaincodeStub stub = new FakeStub();\n        final String chaincodeName = \"ACME_SHIPPING\";\n\n        stub.invokeChaincode(chaincodeName, new ArrayList<>());\n        stub.invokeChaincodeWithStringArgs(chaincodeName, new ArrayList<>(), \"channel\");\n        stub.invokeChaincodeWithStringArgs(chaincodeName, new ArrayList<>());\n        stub.invokeChaincodeWithStringArgs(chaincodeName, \"anvil\", \"tnt\");\n\n        stub.getStringState(\"key\");\n        stub.putPrivateData(\"collection\", \"key\", \"value\");\n        stub.getPrivateDataUTF8(\"collection\", \"key\");\n        stub.putStringState(\"key\", \"value\");\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/ChaincodeTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\n\nimport java.nio.charset.StandardCharsets;\nimport org.junit.jupiter.api.Test;\n\nfinal class ChaincodeTest {\n    @Test\n    void testResponse() {\n        final Chaincode.Response resp = new Chaincode.Response(\n                Chaincode.Response.Status.SUCCESS, \"No message\", \"no payload\".getBytes(StandardCharsets.UTF_8));\n        assertThat(Chaincode.Response.Status.SUCCESS).as(\"Incorrect status\").isEqualTo(resp.getStatus());\n        assertThat(\"No message\").as(\"Incorrect message\").isEqualTo(resp.getMessage());\n        assertThat(\"no payload\").as(\"Incorrect payload\").isEqualTo(resp.getStringPayload());\n    }\n\n    @Test\n    void testResponseWithCode() {\n        Chaincode.Response resp =\n                new Chaincode.Response(200, \"No message\", \"no payload\".getBytes(StandardCharsets.UTF_8));\n        assertThat(Chaincode.Response.Status.SUCCESS).as(\"Incorrect status\").isEqualTo(resp.getStatus());\n        assertThat(200).as(\"Incorrect status\").isEqualTo(resp.getStatusCode());\n        assertThat(\"No message\").as(\"Incorrect message\").isEqualTo(resp.getMessage());\n        assertThat(\"no payload\").as(\"Incorrect payload\").isEqualTo(resp.getStringPayload());\n\n        resp = new Chaincode.Response(404, \"No message\", \"no payload\".getBytes(StandardCharsets.UTF_8));\n        assertThat(404).as(\"Incorrect status\").isEqualTo(resp.getStatusCode());\n        assertThat(\"No message\").as(\"Incorrect message\").isEqualTo(resp.getMessage());\n        assertThat(\"no payload\").as(\"Incorrect payload\").isEqualTo(resp.getStringPayload());\n\n        resp = new Chaincode.Response(\n                Chaincode.Response.Status.ERROR_THRESHOLD, \"No message\", \"no payload\".getBytes(StandardCharsets.UTF_8));\n        assertThat(Chaincode.Response.Status.ERROR_THRESHOLD)\n                .as(\"Incorrect status\")\n                .isEqualTo(resp.getStatus());\n        assertThat(400).as(\"Incorrect status\").isEqualTo(resp.getStatusCode());\n        assertThat(\"No message\").as(\"Incorrect message\").isEqualTo(resp.getMessage());\n        assertThat(\"no payload\").as(\"Incorrect payload\").isEqualTo(resp.getStringPayload());\n    }\n\n    @Test\n    void testStatus() {\n        assertThat(Chaincode.Response.Status.SUCCESS)\n                .as(\"Wrong status\")\n                .isEqualTo(Chaincode.Response.Status.forCode(200));\n        assertThat(Chaincode.Response.Status.ERROR_THRESHOLD)\n                .as(\"Wrong status\")\n                .isEqualTo(Chaincode.Response.Status.forCode(400));\n        assertThat(Chaincode.Response.Status.INTERNAL_SERVER_ERROR)\n                .as(\"Wrong status\")\n                .isEqualTo(Chaincode.Response.Status.forCode(500));\n\n        assertThatThrownBy(() -> Chaincode.Response.Status.forCode(501)).isInstanceOf(IllegalArgumentException.class);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/ChatChaincodeWithPeerTest.java",
    "content": "/*\n * Copyright 2020 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim;\n\nimport static java.nio.charset.StandardCharsets.UTF_8;\nimport static java.util.stream.Collectors.toList;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.INIT;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.INVOKE_CHAINCODE;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.doNothing;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nimport com.google.protobuf.ByteString;\nimport io.grpc.stub.StreamObserver;\nimport java.io.IOException;\nimport java.util.List;\nimport java.util.Properties;\nimport java.util.stream.Stream;\nimport org.hyperledger.fabric.metrics.Metrics;\nimport org.hyperledger.fabric.protos.peer.ChaincodeID;\nimport org.hyperledger.fabric.protos.peer.ChaincodeInput;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.ChaincodeSpec;\nimport org.hyperledger.fabric.shim.chaincode.EmptyChaincode;\nimport org.hyperledger.fabric.shim.utils.MessageUtil;\nimport org.hyperledger.fabric.traces.Traces;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport uk.org.webcompere.systemstubs.environment.EnvironmentVariables;\nimport uk.org.webcompere.systemstubs.jupiter.SystemStub;\nimport uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension;\n\n@ExtendWith(SystemStubsExtension.class)\nfinal class ChatChaincodeWithPeerTest {\n    private static final String TEST_CHANNEL = \"testChannel\";\n\n    @SystemStub\n    private final EnvironmentVariables environmentVariables = new EnvironmentVariables();\n\n    @BeforeEach\n    void setEnv() {\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"mycc\");\n        environmentVariables.set(\"CORE_PEER_ADDRESS\", \"localhost:7052\");\n        environmentVariables.set(\"CORE_PEER_TLS_ENABLED\", \"false\");\n        environmentVariables.set(\"CORE_PEER_TLS_ROOTCERT_FILE\", \"src/test/resources/ca.crt\");\n        environmentVariables.set(\"CORE_TLS_CLIENT_KEY_PATH\", \"src/test/resources/client.key.enc\");\n        environmentVariables.set(\"CORE_TLS_CLIENT_CERT_PATH\", \"src/test/resources/client.crt.enc\");\n    }\n\n    @AfterEach\n    void clearEnv() {\n        environmentVariables.remove(\"CORE_CHAINCODE_ID_NAME\");\n        environmentVariables.remove(\"CORE_PEER_ADDRESS\");\n        environmentVariables.remove(\"CORE_PEER_TLS_ENABLED\");\n        environmentVariables.remove(\"CORE_PEER_TLS_ROOTCERT_FILE\");\n        environmentVariables.remove(\"CORE_TLS_CLIENT_KEY_PATH\");\n        environmentVariables.remove(\"CORE_TLS_CLIENT_CERT_PATH\");\n    }\n\n    @Test\n    void initNull() throws IOException {\n        Assertions.assertThrows(\n                IOException.class,\n                () -> {\n                    ChatChaincodeWithPeer chatChaincodeWithPeer = new ChatChaincodeWithPeer(null);\n                },\n                \"chaincodeBase can't be null\");\n    }\n\n    @Test\n    void init() {\n        ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n        chaincodeBase.validateOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Metrics.initialize(props);\n        ChatChaincodeWithPeer chatChaincodeWithPeer = null;\n        try {\n            chatChaincodeWithPeer = new ChatChaincodeWithPeer(chaincodeBase);\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n        assertNotNull(chatChaincodeWithPeer);\n    }\n\n    @Test\n    void initEmptyId() throws IOException {\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"\");\n\n        Assertions.assertThrows(\n                IllegalArgumentException.class,\n                () -> {\n                    ChaincodeBase chaincodeBase = new EmptyChaincode();\n                    chaincodeBase.processEnvironmentOptions();\n                    chaincodeBase.validateOptions();\n\n                    Properties props = chaincodeBase.getChaincodeConfig();\n                    Metrics.initialize(props);\n                    Traces.initialize(props);\n                    ChatChaincodeWithPeer chatChaincodeWithPeer = new ChatChaincodeWithPeer(chaincodeBase);\n                },\n                \"chaincode id not set, set env 'CORE_CHAINCODE_ID_NAME', for example 'CORE_CHAINCODE_ID_NAME=mycc'\");\n    }\n\n    @Test\n    void connectEnvNotSet() throws IOException {\n        clearEnv();\n\n        Assertions.assertThrows(IllegalArgumentException.class, () -> {\n            ChaincodeBase chaincodeBase = new EmptyChaincode();\n            ChatChaincodeWithPeer chatChaincodeWithPeer = new ChatChaincodeWithPeer(chaincodeBase);\n        });\n    }\n\n    @Test\n    void connectNull() throws IOException {\n        ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n        chaincodeBase.validateOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Metrics.initialize(props);\n        Traces.initialize(props);\n        ChatChaincodeWithPeer chatChaincodeWithPeer = new ChatChaincodeWithPeer(chaincodeBase);\n        assertNull(chatChaincodeWithPeer.connect(null));\n    }\n\n    @Test\n    @SuppressWarnings(\"PMD.SystemPrintln\")\n    void connectAndReceiveRegister() throws IOException {\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"mycc\");\n        ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n        chaincodeBase.validateOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Traces.initialize(props);\n        Metrics.initialize(props);\n\n        ChatChaincodeWithPeer chatChaincodeWithPeer = new ChatChaincodeWithPeer(chaincodeBase);\n        final StreamObserver<ChaincodeMessage> connect = chatChaincodeWithPeer.connect(new StreamObserver<>() {\n            @Override\n            public void onNext(final ChaincodeMessage value) {\n                assertEquals(ChaincodeMessage.Type.REGISTER, value.getType());\n                assertEquals(\"\\u0012\\u0004mycc\", value.getPayload().toStringUtf8());\n            }\n\n            @Override\n            public void onError(final Throwable t) {\n                assertNull(t);\n            }\n\n            @Override\n            public void onCompleted() {}\n        });\n        assertNotNull(connect);\n\n        final ByteString payload = ChaincodeInput.newBuilder()\n                .addArgs(ByteString.copyFromUtf8(\"\"))\n                .build()\n                .toByteString();\n        final ChaincodeMessage initMsg = MessageUtil.newEventMessage(INIT, TEST_CHANNEL, \"0\", payload, null);\n        connect.onNext(initMsg);\n\n        {\n            final List<byte[]> args =\n                    Stream.of(\"invoke\", \"a\", \"1\").map(x -> x.getBytes(UTF_8)).collect(toList());\n            final ByteString invocationSpecPayload = ChaincodeSpec.newBuilder()\n                    .setChaincodeId(ChaincodeID.newBuilder()\n                            .setName(chaincodeBase.getId())\n                            .build())\n                    .setInput(ChaincodeInput.newBuilder()\n                            .addAllArgs(args.stream().map(ByteString::copyFrom).collect(toList()))\n                            .build())\n                    .build()\n                    .toByteString();\n\n            final ChaincodeMessage invokeChaincodeMessage = ChaincodeMessage.newBuilder()\n                    .setType(INVOKE_CHAINCODE)\n                    .setChannelId(TEST_CHANNEL)\n                    .setTxid(\"1\")\n                    .setPayload(invocationSpecPayload)\n                    .build();\n            connect.onNext(invokeChaincodeMessage);\n            System.out.println(invokeChaincodeMessage.getPayload().toStringUtf8());\n        }\n\n        {\n            final List<byte[]> args =\n                    Stream.of(\"invoke\", \"a\", \"1\").map(x -> x.getBytes(UTF_8)).collect(toList());\n            final ByteString invocationSpecPayload = ChaincodeSpec.newBuilder()\n                    .setChaincodeId(ChaincodeID.newBuilder()\n                            .setName(chaincodeBase.getId())\n                            .build())\n                    .setInput(ChaincodeInput.newBuilder()\n                            .addAllArgs(args.stream().map(ByteString::copyFrom).collect(toList()))\n                            .build())\n                    .build()\n                    .toByteString();\n\n            final ChaincodeMessage invokeChaincodeMessage = ChaincodeMessage.newBuilder()\n                    .setType(INVOKE_CHAINCODE)\n                    .setChannelId(TEST_CHANNEL)\n                    .setTxid(\"2\")\n                    .setPayload(invocationSpecPayload)\n                    .build();\n            connect.onNext(invokeChaincodeMessage);\n            System.out.println(invokeChaincodeMessage.getPayload().toStringUtf8());\n        }\n    }\n\n    @Test\n    void connectAndReceiveRegisterComplete() throws IOException {\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"mycc\");\n        ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n        chaincodeBase.validateOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Traces.initialize(props);\n        Metrics.initialize(props);\n\n        ChatChaincodeWithPeer chatChaincodeWithPeer = new ChatChaincodeWithPeer(chaincodeBase);\n        final StreamObserver<ChaincodeMessage> connect = chatChaincodeWithPeer.connect(new StreamObserver<>() {\n            @Override\n            public void onNext(final ChaincodeMessage value) {\n                assertEquals(ChaincodeMessage.Type.REGISTER, value.getType());\n                assertEquals(\"\\u0012\\u0004mycc\", value.getPayload().toStringUtf8());\n            }\n\n            @Override\n            public void onError(final Throwable t) {\n                assertNull(t);\n            }\n\n            @Override\n            public void onCompleted() {}\n        });\n        connect.onCompleted();\n    }\n\n    @Test\n    void connectAndReceiveRegisterException() throws IOException {\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"mycc\");\n        ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n        chaincodeBase.validateOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Traces.initialize(props);\n        Metrics.initialize(props);\n\n        ChatChaincodeWithPeer chatChaincodeWithPeer = new ChatChaincodeWithPeer(chaincodeBase);\n        final StreamObserver<ChaincodeMessage> connect = chatChaincodeWithPeer.connect(new StreamObserver<>() {\n            @Override\n            public void onNext(final ChaincodeMessage value) {}\n\n            @Override\n            public void onError(final Throwable t) {}\n\n            @Override\n            public void onCompleted() {}\n        });\n        connect.onError(new Exception(\"some_error\"));\n    }\n\n    @Test\n    @SuppressWarnings(\"PMD.AvoidThrowingRawExceptionTypes\")\n    void connectOnCompletedException() throws IOException {\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"mycc\");\n        ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n        chaincodeBase.validateOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Metrics.initialize(props);\n        Traces.initialize(props);\n\n        ChatChaincodeWithPeer chatChaincodeWithPeer = new ChatChaincodeWithPeer(chaincodeBase);\n\n        Assertions.assertDoesNotThrow(\n                () -> {\n                    chatChaincodeWithPeer.connect(new StreamObserver<>() {\n                        @Override\n                        public void onNext(final ChaincodeMessage value) {}\n\n                        @Override\n                        public void onError(final Throwable t) {}\n\n                        @Override\n                        public void onCompleted() {\n                            throw new RuntimeException(\"some_error\");\n                        }\n                    });\n                },\n                \"some_error\");\n    }\n\n    @Test\n    void testMockChaincodeBase() throws IOException {\n        final ChaincodeBase mockChaincodeBase = mock(ChaincodeBase.class);\n        when(mockChaincodeBase.getId()).thenReturn(\"ccid_1234\");\n        when(mockChaincodeBase.connectToPeer(any())).thenReturn(null);\n\n        ChatChaincodeWithPeer chatChaincodeWithPeer = new ChatChaincodeWithPeer(mockChaincodeBase);\n        assertNotNull(chatChaincodeWithPeer);\n\n        assertNull(chatChaincodeWithPeer.connect(new StreamObserver<>() {\n            @Override\n            public void onNext(final ChaincodeMessage value) {}\n\n            @Override\n            public void onError(final Throwable t) {}\n\n            @Override\n            public void onCompleted() {}\n        }));\n    }\n\n    @Test\n    void testMockChaincodeBaseThrowIOException() throws IOException {\n        final ChaincodeBase mockChaincodeBase = mock(ChaincodeBase.class);\n        when(mockChaincodeBase.getId()).thenReturn(\"ccid_1234\");\n        final IOException expectedException = new IOException(\"some_error\");\n        when(mockChaincodeBase.connectToPeer(any())).thenThrow(expectedException);\n        doNothing().when(mockChaincodeBase).validateOptions();\n\n        ChatChaincodeWithPeer chatChaincodeWithPeer = new ChatChaincodeWithPeer(mockChaincodeBase);\n        assertNotNull(chatChaincodeWithPeer);\n\n        assertNull(chatChaincodeWithPeer.connect(new StreamObserver<>() {\n            @Override\n            public void onNext(final ChaincodeMessage value) {}\n\n            @Override\n            public void onError(final Throwable t) {\n                assertEquals(expectedException, t);\n            }\n\n            @Override\n            public void onCompleted() {}\n        }));\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/NettyGrpcServerTest.java",
    "content": "/*\n * Copyright 2020 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim;\n\nimport java.io.IOException;\nimport java.net.URISyntaxException;\nimport java.util.Properties;\nimport org.hyperledger.fabric.metrics.Metrics;\nimport org.hyperledger.fabric.shim.chaincode.EmptyChaincode;\nimport org.hyperledger.fabric.traces.Traces;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport uk.org.webcompere.systemstubs.environment.EnvironmentVariables;\nimport uk.org.webcompere.systemstubs.jupiter.SystemStub;\nimport uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension;\n\n@ExtendWith(SystemStubsExtension.class)\nfinal class NettyGrpcServerTest {\n    @SystemStub\n    private final EnvironmentVariables environmentVariables = new EnvironmentVariables();\n\n    @BeforeEach\n    void setEnv() {\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"mycc\");\n        environmentVariables.set(\"CORE_PEER_ADDRESS\", \"localhost:7052\");\n        environmentVariables.set(\"CORE_PEER_TLS_ENABLED\", \"false\");\n        environmentVariables.set(\"CORE_PEER_TLS_ROOTCERT_FILE\", \"src/test/resources/ca.crt\");\n        environmentVariables.set(\"CORE_TLS_CLIENT_KEY_PATH\", \"src/test/resources/client.key.enc\");\n        environmentVariables.set(\"CORE_TLS_CLIENT_CERT_PATH\", \"src/test/resources/client.crt.enc\");\n        environmentVariables.set(\"CHAINCODE_SERVER_ADDRESS\", \"0.0.0.0:9999\");\n    }\n\n    @AfterEach\n    void clearEnv() {\n        environmentVariables.remove(\"CORE_CHAINCODE_ID_NAME\");\n        environmentVariables.remove(\"CORE_PEER_ADDRESS\");\n        environmentVariables.remove(\"CORE_PEER_TLS_ENABLED\");\n        environmentVariables.remove(\"CORE_PEER_TLS_ROOTCERT_FILE\");\n        environmentVariables.remove(\"CORE_TLS_CLIENT_KEY_PATH\");\n        environmentVariables.remove(\"CORE_TLS_CLIENT_CERT_PATH\");\n        environmentVariables.remove(\"CHAINCODE_SERVER_ADDRESS\");\n    }\n\n    @Test\n    void initNoTls() {\n        try {\n            final ChaincodeBase chaincodeBase = new EmptyChaincode();\n            chaincodeBase.processEnvironmentOptions();\n            ChaincodeServer chaincodeServer =\n                    new NettyChaincodeServer(chaincodeBase, chaincodeBase.getChaincodeServerConfig());\n        } catch (IOException | URISyntaxException e) {\n            e.printStackTrace();\n        }\n    }\n\n    @Test\n    void validationNoChaincodeServerPropertiesg() {\n        Assertions.assertThrows(\n                IllegalArgumentException.class,\n                () -> {\n                    final ChaincodeBase chaincodeBase = new EmptyChaincode();\n                    ChaincodeServer chaincodeServer = new NettyChaincodeServer(chaincodeBase, null);\n                },\n                \"ChaincodeServerProperties must be specified\");\n    }\n\n    @Test\n    void validationPortChaincodeServer() {\n        Assertions.assertThrows(\n                IllegalArgumentException.class,\n                () -> {\n                    final ChaincodeBase chaincodeBase = new EmptyChaincode();\n                    final ChaincodeServerProperties chaincodeServerProperties = new ChaincodeServerProperties();\n                    chaincodeServerProperties.setServerAddress(null);\n                    ChaincodeServer chaincodeServer =\n                            new NettyChaincodeServer(chaincodeBase, chaincodeServerProperties);\n                },\n                \"ChaincodeServerProperties.getServerAddress() must be set\");\n    }\n\n    @Test\n    void validationKeepAliveTimeMinutes() {\n        Assertions.assertThrows(\n                IllegalArgumentException.class,\n                () -> {\n                    final ChaincodeBase chaincodeBase = new EmptyChaincode();\n                    final ChaincodeServerProperties chaincodeServerProperties = new ChaincodeServerProperties();\n                    chaincodeServerProperties.setKeepAliveTimeMinutes(-1);\n                    ChaincodeServer chaincodeServer =\n                            new NettyChaincodeServer(chaincodeBase, chaincodeServerProperties);\n                },\n                \"ChaincodeServerProperties.getKeepAliveTimeMinutes() must be more then 0\");\n    }\n\n    @Test\n    void validationKeepAliveTimeoutSeconds() {\n        Assertions.assertThrows(\n                IllegalArgumentException.class,\n                () -> {\n                    final ChaincodeBase chaincodeBase = new EmptyChaincode();\n                    final ChaincodeServerProperties chaincodeServerProperties = new ChaincodeServerProperties();\n                    chaincodeServerProperties.setKeepAliveTimeoutSeconds(-1);\n                    ChaincodeServer chaincodeServer =\n                            new NettyChaincodeServer(chaincodeBase, chaincodeServerProperties);\n                },\n                \"ChaincodeServerProperties.getKeepAliveTimeoutSeconds() must be more then 0\");\n    }\n\n    @Test\n    void validationPermitKeepAliveTimeMinutes() {\n        Assertions.assertThrows(\n                IllegalArgumentException.class,\n                () -> {\n                    final ChaincodeBase chaincodeBase = new EmptyChaincode();\n                    final ChaincodeServerProperties chaincodeServerProperties = new ChaincodeServerProperties();\n                    chaincodeServerProperties.setPermitKeepAliveTimeMinutes(-1);\n                    ChaincodeServer chaincodeServer =\n                            new NettyChaincodeServer(chaincodeBase, chaincodeServerProperties);\n                },\n                \"ChaincodeServerProperties.getPermitKeepAliveTimeMinutes() must be more then 0\");\n    }\n\n    @Test\n    void validationMaxConnectionAgeSeconds() {\n        Assertions.assertThrows(\n                IllegalArgumentException.class,\n                () -> {\n                    final ChaincodeBase chaincodeBase = new EmptyChaincode();\n                    final ChaincodeServerProperties chaincodeServerProperties = new ChaincodeServerProperties();\n                    chaincodeServerProperties.setMaxConnectionAgeSeconds(-1);\n                    ChaincodeServer chaincodeServer =\n                            new NettyChaincodeServer(chaincodeBase, chaincodeServerProperties);\n                },\n                \"ChaincodeServerProperties.getMaxConnectionAgeSeconds() must be more then 0\");\n    }\n\n    @Test\n    void validationMaxInboundMetadataSize() {\n        Assertions.assertThrows(\n                IllegalArgumentException.class,\n                () -> {\n                    final ChaincodeBase chaincodeBase = new EmptyChaincode();\n                    final ChaincodeServerProperties chaincodeServerProperties = new ChaincodeServerProperties();\n                    chaincodeServerProperties.setMaxInboundMetadataSize(-1);\n                    ChaincodeServer chaincodeServer =\n                            new NettyChaincodeServer(chaincodeBase, chaincodeServerProperties);\n                },\n                \"ChaincodeServerProperties.getMaxInboundMetadataSize() must be more then 0\");\n    }\n\n    @Test\n    void validationMaxInboundMessageSize() {\n        Assertions.assertThrows(\n                IllegalArgumentException.class,\n                () -> {\n                    final ChaincodeBase chaincodeBase = new EmptyChaincode();\n                    final ChaincodeServerProperties chaincodeServerProperties = new ChaincodeServerProperties();\n                    chaincodeServerProperties.setMaxInboundMessageSize(-1);\n                    ChaincodeServer chaincodeServer =\n                            new NettyChaincodeServer(chaincodeBase, chaincodeServerProperties);\n                },\n                \"ChaincodeServerProperties.getMaxInboundMessageSize() must be more then 0\");\n    }\n\n    @Test\n    void validationTlsEnabledButKeyNotSet() {\n        Assertions.assertThrows(\n                IllegalArgumentException.class,\n                () -> {\n                    final ChaincodeBase chaincodeBase = new EmptyChaincode();\n                    final ChaincodeServerProperties chaincodeServerProperties = new ChaincodeServerProperties();\n                    chaincodeServerProperties.setTlsEnabled(true);\n                    chaincodeServerProperties.setKeyFile(null);\n                    chaincodeServerProperties.setKeyCertChainFile(null);\n                    chaincodeServerProperties.setKeyPassword(null);\n                    ChaincodeServer chaincodeServer =\n                            new NettyChaincodeServer(chaincodeBase, chaincodeServerProperties);\n                },\n                \"ChaincodeServerProperties.getMaxInboundMessageSize() must be more then 0\");\n    }\n\n    @Test\n    void initNull() {\n        Assertions.assertThrows(\n                IllegalArgumentException.class,\n                () -> {\n                    ChaincodeServer chaincodeServer = new NettyChaincodeServer(null, new ChaincodeServerProperties());\n                },\n                \"chaincode must be specified\");\n    }\n\n    @Test\n    void initNullEnvNotSet() {\n        clearEnv();\n        Assertions.assertThrows(IllegalArgumentException.class, () -> {\n            ChaincodeServer chaincodeServer = new NettyChaincodeServer(null, new ChaincodeServerProperties());\n        });\n    }\n\n    @Test\n    void initEnvNotSet() {\n        clearEnv();\n        Assertions.assertThrows(IllegalArgumentException.class, () -> {\n            final ChaincodeBase chaincodeBase = new EmptyChaincode();\n            ChaincodeServer chaincodeServer = new NettyChaincodeServer(chaincodeBase, new ChaincodeServerProperties());\n        });\n    }\n\n    @Test\n    void initEnvSetPortChaincodeServerAndCoreChaincodeIdName() throws IOException, URISyntaxException {\n        clearEnv();\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"mycc\");\n        environmentVariables.set(\"CHAINCODE_SERVER_ADDRESS\", \"0.0.0.0:9999\");\n        ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Metrics.initialize(props);\n        Traces.initialize(props);\n\n        ChaincodeServer chaincodeServer =\n                new NettyChaincodeServer(chaincodeBase, chaincodeBase.getChaincodeServerConfig());\n    }\n\n    @Test\n    void startAndStopSetCoreChaincodeIdName() {\n        clearEnv();\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"mycc\");\n        environmentVariables.set(\"CHAINCODE_SERVER_ADDRESS\", \"0.0.0.0:9999\");\n        try {\n            ChaincodeBase chaincodeBase = new EmptyChaincode();\n            chaincodeBase.processEnvironmentOptions();\n            Properties props = chaincodeBase.getChaincodeConfig();\n            Metrics.initialize(props);\n            Traces.initialize(props);\n\n            ChaincodeServer chaincodeServer =\n                    new NettyChaincodeServer(chaincodeBase, chaincodeBase.getChaincodeServerConfig());\n            new Thread(() -> {\n                        try {\n                            chaincodeServer.start();\n                        } catch (IOException | InterruptedException e) {\n                            e.printStackTrace();\n                        }\n                    })\n                    .start();\n            try {\n                Thread.sleep(1000);\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n\n            chaincodeServer.stop();\n        } catch (IOException | URISyntaxException e) {\n            e.printStackTrace();\n        }\n    }\n\n    @Test\n    void startAndStop() {\n        try {\n            final ChaincodeBase chaincodeBase = new EmptyChaincode();\n            chaincodeBase.processEnvironmentOptions();\n            ChaincodeServer chaincodeServer =\n                    new NettyChaincodeServer(chaincodeBase, chaincodeBase.getChaincodeServerConfig());\n            new Thread(() -> {\n                        try {\n                            chaincodeServer.start();\n                        } catch (IOException | InterruptedException e) {\n                            e.printStackTrace();\n                        }\n                    })\n                    .start();\n            try {\n                Thread.sleep(1000);\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n\n            chaincodeServer.stop();\n        } catch (IOException | URISyntaxException e) {\n            e.printStackTrace();\n        }\n    }\n\n    @Test\n    void startAndStopTlsPassword() {\n        try {\n            final ChaincodeBase chaincodeBase = new EmptyChaincode();\n            chaincodeBase.processEnvironmentOptions();\n            final ChaincodeServerProperties chaincodeServerProperties = chaincodeBase.getChaincodeServerConfig();\n            chaincodeServerProperties.setTlsEnabled(true);\n            chaincodeServerProperties.setKeyFile(\"src/test/resources/client.key.password-protected\");\n            chaincodeServerProperties.setKeyCertChainFile(\"src/test/resources/client.crt\");\n            chaincodeServerProperties.setKeyPassword(\"test\");\n            ChaincodeServer chaincodeServer = new NettyChaincodeServer(chaincodeBase, chaincodeServerProperties);\n            new Thread(() -> {\n                        try {\n                            chaincodeServer.start();\n                        } catch (IOException | InterruptedException e) {\n                            e.printStackTrace();\n                        }\n                    })\n                    .start();\n            try {\n                Thread.sleep(1000);\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n\n            chaincodeServer.stop();\n        } catch (IOException | URISyntaxException e) {\n            e.printStackTrace();\n        }\n    }\n\n    @Test\n    void startAndStopTlsWithoutPassword() {\n        try {\n            final ChaincodeBase chaincodeBase = new EmptyChaincode();\n            chaincodeBase.processEnvironmentOptions();\n            final ChaincodeServerProperties chaincodeServerProperties = chaincodeBase.getChaincodeServerConfig();\n            chaincodeServerProperties.setTlsEnabled(true);\n            chaincodeServerProperties.setKeyFile(\"src/test/resources/client.key\");\n            chaincodeServerProperties.setKeyCertChainFile(\"src/test/resources/client.crt\");\n            ChaincodeServer chaincodeServer = new NettyChaincodeServer(chaincodeBase, chaincodeServerProperties);\n            new Thread(() -> {\n                        try {\n                            chaincodeServer.start();\n                        } catch (IOException | InterruptedException e) {\n                            e.printStackTrace();\n                        }\n                    })\n                    .start();\n            try {\n                Thread.sleep(1000);\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n\n            chaincodeServer.stop();\n        } catch (IOException | URISyntaxException e) {\n            e.printStackTrace();\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/chaincode/EmptyChaincode.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.chaincode;\n\nimport org.hyperledger.fabric.shim.ChaincodeBase;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.hyperledger.fabric.shim.ResponseUtils;\n\npublic final class EmptyChaincode extends ChaincodeBase {\n    @Override\n    public Response init(final ChaincodeStub stub) {\n        return ResponseUtils.newSuccessResponse();\n    }\n\n    @Override\n    public Response invoke(final ChaincodeStub stub) {\n        return ResponseUtils.newSuccessResponse();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/ext/sbe/StateBasedEndorsementTest.java",
    "content": "/*\n * Copyright 2019 IBM DTCC All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.ext.sbe;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\n\nimport org.junit.jupiter.api.Test;\n\nfinal class StateBasedEndorsementTest {\n    @Test\n    void testRoleType() {\n        assertThat(StateBasedEndorsement.RoleType.forVal(\"MEMBER\"))\n                .isEqualTo(StateBasedEndorsement.RoleType.RoleTypeMember);\n        assertThat(StateBasedEndorsement.RoleType.forVal(\"PEER\"))\n                .isEqualTo(StateBasedEndorsement.RoleType.RoleTypePeer);\n\n        assertThatThrownBy(() -> StateBasedEndorsement.RoleType.forVal(\"NONEXIST\"))\n                .isInstanceOf(IllegalArgumentException.class);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/ext/sbe/impl/StateBasedEndorsementFactoryTest.java",
    "content": "/*\n * Copyright 2019 IBM DTCC All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.ext.sbe.impl;\n\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\nimport static org.junit.jupiter.api.Assertions.assertInstanceOf;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport org.junit.jupiter.api.Test;\n\nfinal class StateBasedEndorsementFactoryTest {\n    @Test\n    void getInstance() {\n        assertNotNull(StateBasedEndorsementFactory.getInstance());\n        assertInstanceOf(StateBasedEndorsementFactory.class, StateBasedEndorsementFactory.getInstance());\n    }\n\n    @Test\n    void newStateBasedEndorsement() {\n        assertNotNull(StateBasedEndorsementFactory.getInstance().newStateBasedEndorsement(new byte[] {}));\n        assertThatThrownBy(() -> StateBasedEndorsementFactory.getInstance().newStateBasedEndorsement(new byte[] {0}))\n                .isInstanceOf(IllegalArgumentException.class);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/ext/sbe/impl/StateBasedEndorsementImplTest.java",
    "content": "/*\n * Copyright 2019 IBM DTCC All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.ext.sbe.impl;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.contains;\nimport static org.hamcrest.Matchers.hasSize;\nimport static org.hamcrest.Matchers.is;\nimport static org.hamcrest.Matchers.not;\nimport static org.hamcrest.Matchers.nullValue;\nimport static org.junit.jupiter.api.Assertions.assertArrayEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.List;\nimport org.hyperledger.fabric.protos.common.MSPRole.MSPRoleType;\nimport org.hyperledger.fabric.shim.ext.sbe.StateBasedEndorsement;\nimport org.hyperledger.fabric.shim.ext.sbe.StateBasedEndorsement.RoleType;\nimport org.junit.jupiter.api.Test;\n\nfinal class StateBasedEndorsementImplTest {\n\n    @Test\n    void addOrgs() {\n        // add an org\n        final StateBasedEndorsement ep =\n                StateBasedEndorsementFactory.getInstance().newStateBasedEndorsement(null);\n        ep.addOrgs(RoleType.RoleTypePeer, \"Org1\");\n\n        final byte[] epBytes = ep.policy();\n        assertThat(epBytes, is(not(nullValue())));\n        assertTrue(epBytes.length > 0);\n        final byte[] expectedEPBytes = StateBasedEndorsementUtils.signedByFabricEntity(\"Org1\", MSPRoleType.PEER)\n                .toByteString()\n                .toByteArray();\n        assertArrayEquals(expectedEPBytes, epBytes);\n    }\n\n    @Test\n    void delOrgs() {\n\n        final byte[] initEPBytes = StateBasedEndorsementUtils.signedByFabricEntity(\"Org1\", MSPRoleType.PEER)\n                .toByteString()\n                .toByteArray();\n        final StateBasedEndorsement ep =\n                StateBasedEndorsementFactory.getInstance().newStateBasedEndorsement(initEPBytes);\n        final List<String> listOrgs = ep.listOrgs();\n\n        assertThat(listOrgs, is(not(nullValue())));\n        assertThat(listOrgs, contains(\"Org1\"));\n        assertThat(listOrgs, hasSize(1));\n\n        ep.addOrgs(RoleType.RoleTypeMember, \"Org2\");\n        ep.delOrgs(\"Org1\");\n\n        final byte[] epBytes = ep.policy();\n\n        assertThat(epBytes, is(not(nullValue())));\n        assertTrue(epBytes.length > 0);\n        final byte[] expectedEPBytes = StateBasedEndorsementUtils.signedByFabricEntity(\"Org2\", MSPRoleType.MEMBER)\n                .toByteString()\n                .toByteArray();\n        assertArrayEquals(expectedEPBytes, epBytes);\n    }\n\n    @Test\n    void listOrgs() {\n        final byte[] initEPBytes = StateBasedEndorsementUtils.signedByFabricEntity(\"Org1\", MSPRoleType.PEER)\n                .toByteString()\n                .toByteArray();\n        final StateBasedEndorsement ep =\n                StateBasedEndorsementFactory.getInstance().newStateBasedEndorsement(initEPBytes);\n        final List<String> listOrgs = ep.listOrgs();\n\n        assertThat(listOrgs, is(not(nullValue())));\n        assertThat(listOrgs, hasSize(1));\n        assertThat(listOrgs, contains(\"Org1\"));\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/fvt/ChaincodeFVTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.fvt;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.is;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.COMPLETED;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.INIT;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.READY;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.REGISTER;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.RESPONSE;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.TRANSACTION;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.fail;\n\nimport com.google.protobuf.ByteString;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport org.hyperledger.fabric.protos.peer.ChaincodeInput;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.Response;\nimport org.hyperledger.fabric.shim.ChaincodeBase;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.hyperledger.fabric.shim.ResponseUtils;\nimport org.hyperledger.fabric.shim.chaincode.EmptyChaincode;\nimport org.hyperledger.fabric.shim.ext.sbe.StateBasedEndorsement;\nimport org.hyperledger.fabric.shim.ext.sbe.impl.StateBasedEndorsementFactory;\nimport org.hyperledger.fabric.shim.ledger.KeyModification;\nimport org.hyperledger.fabric.shim.ledger.KeyValue;\nimport org.hyperledger.fabric.shim.ledger.QueryResultsIterator;\nimport org.hyperledger.fabric.shim.mock.peer.ChaincodeMockPeer;\nimport org.hyperledger.fabric.shim.mock.peer.CompleteStep;\nimport org.hyperledger.fabric.shim.mock.peer.DelValueStep;\nimport org.hyperledger.fabric.shim.mock.peer.ErrorResponseStep;\nimport org.hyperledger.fabric.shim.mock.peer.GetHistoryForKeyStep;\nimport org.hyperledger.fabric.shim.mock.peer.GetQueryResultStep;\nimport org.hyperledger.fabric.shim.mock.peer.GetStateByRangeStep;\nimport org.hyperledger.fabric.shim.mock.peer.GetStateMetadata;\nimport org.hyperledger.fabric.shim.mock.peer.GetValueStep;\nimport org.hyperledger.fabric.shim.mock.peer.InvokeChaincodeStep;\nimport org.hyperledger.fabric.shim.mock.peer.PutStateMetadata;\nimport org.hyperledger.fabric.shim.mock.peer.PutValueStep;\nimport org.hyperledger.fabric.shim.mock.peer.QueryCloseStep;\nimport org.hyperledger.fabric.shim.mock.peer.QueryNextStep;\nimport org.hyperledger.fabric.shim.mock.peer.RegisterStep;\nimport org.hyperledger.fabric.shim.mock.peer.ScenarioStep;\nimport org.hyperledger.fabric.shim.utils.MessageUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport uk.org.webcompere.systemstubs.environment.EnvironmentVariables;\nimport uk.org.webcompere.systemstubs.jupiter.SystemStub;\nimport uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension;\n\n@ExtendWith(SystemStubsExtension.class)\nfinal class ChaincodeFVTest {\n\n    @SystemStub\n    private final EnvironmentVariables environmentVariables = new EnvironmentVariables();\n\n    private ChaincodeMockPeer server;\n\n    @AfterEach\n    void afterTest() throws Exception {\n        if (server != null) {\n            server.stop();\n            server = null;\n        }\n    }\n\n    @Test\n    void testRegister() throws Exception {\n        final ChaincodeBase cb = new EmptyChaincode();\n\n        final List<ScenarioStep> scenario = new ArrayList<>();\n        scenario.add(new RegisterStep());\n\n        server = ChaincodeMockPeer.startServer(scenario);\n\n        cb.start(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 1, 5000, TimeUnit.MILLISECONDS);\n\n        assertThat(server.getLastMessageSend().getType(), is(READY));\n        assertThat(server.getLastMessageRcvd().getType(), is(REGISTER));\n    }\n\n    @Test\n    void testRegisterAndEmptyInit() throws Exception {\n        final ChaincodeBase cb = new ChaincodeBase() {\n            @Override\n            public Response init(final ChaincodeStub stub) {\n                return ResponseUtils.newSuccessResponse();\n            }\n\n            @Override\n            public Response invoke(final ChaincodeStub stub) {\n                return ResponseUtils.newSuccessResponse();\n            }\n        };\n\n        final ByteString payload = ChaincodeInput.newBuilder()\n                .addArgs(ByteString.copyFromUtf8(\"\"))\n                .build()\n                .toByteString();\n        final ChaincodeMessage initMsg = MessageUtil.newEventMessage(INIT, \"testChannel\", \"0\", payload, null);\n\n        final List<ScenarioStep> scenario = new ArrayList<>();\n        scenario.add(new RegisterStep());\n        scenario.add(new CompleteStep());\n\n        server = ChaincodeMockPeer.startServer(scenario);\n\n        cb.start(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 1, 5000, TimeUnit.MILLISECONDS);\n\n        server.send(initMsg);\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 2, 5000, TimeUnit.MILLISECONDS);\n\n        assertThat(server.getLastMessageSend().getType(), is(INIT));\n        assertThat(server.getLastMessageRcvd().getType(), is(COMPLETED));\n    }\n\n    @Test\n    void testInitAndInvoke() throws Exception {\n        final ChaincodeBase cb = new ChaincodeBase() {\n            @Override\n            public Response init(final ChaincodeStub stub) {\n                assertThat(stub.getFunction(), is(\"init\"));\n                assertThat(stub.getArgs().size(), is(3));\n                stub.putState(\"a\", ByteString.copyFromUtf8(\"100\").toByteArray());\n                return ResponseUtils.newSuccessResponse(\"OK response1\");\n            }\n\n            @Override\n            public Response invoke(final ChaincodeStub stub) {\n                assertThat(stub.getFunction(), is(\"invoke\"));\n                assertThat(stub.getArgs().size(), is(3));\n                final String aKey = stub.getStringArgs().get(1);\n                assertThat(aKey, is(\"a\"));\n                stub.getStringState(aKey);\n                stub.putState(aKey, ByteString.copyFromUtf8(\"120\").toByteArray());\n                stub.delState(\"delKey\");\n                return ResponseUtils.newSuccessResponse(\"OK response2\");\n            }\n        };\n\n        final ByteString initPayload = ChaincodeInput.newBuilder()\n                .addArgs(ByteString.copyFromUtf8(\"init\"))\n                .addArgs(ByteString.copyFromUtf8(\"a\"))\n                .addArgs(ByteString.copyFromUtf8(\"100\"))\n                .build()\n                .toByteString();\n        final ChaincodeMessage initMsg = MessageUtil.newEventMessage(INIT, \"testChannel\", \"0\", initPayload, null);\n\n        final List<ScenarioStep> scenario = new ArrayList<>();\n        scenario.add(new RegisterStep());\n        scenario.add(new PutValueStep(\"100\"));\n        scenario.add(new CompleteStep());\n        scenario.add(new GetValueStep(\"100\"));\n        scenario.add(new PutValueStep(\"120\"));\n        scenario.add(new DelValueStep());\n        scenario.add(new CompleteStep());\n\n        setLogLevel(\"DEBUG\");\n        server = ChaincodeMockPeer.startServer(scenario);\n\n        cb.start(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 1, 5000, TimeUnit.MILLISECONDS);\n\n        server.send(initMsg);\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 3, 5000, TimeUnit.MILLISECONDS);\n\n        assertThat(server.getLastMessageSend().getType(), is(INIT));\n        assertThat(server.getLastMessageRcvd().getType(), is(COMPLETED));\n        assertThat(Response.parseFrom(server.getLastMessageRcvd().getPayload()).getMessage(), is(\"OK response1\"));\n\n        final ByteString invokePayload = ChaincodeInput.newBuilder()\n                .addArgs(ByteString.copyFromUtf8(\"invoke\"))\n                .addArgs(ByteString.copyFromUtf8(\"a\"))\n                .addArgs(ByteString.copyFromUtf8(\"10\"))\n                .build()\n                .toByteString();\n        final ChaincodeMessage invokeMsg =\n                MessageUtil.newEventMessage(TRANSACTION, \"testChannel\", \"0\", invokePayload, null);\n\n        server.send(invokeMsg);\n\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 7, 5000, TimeUnit.MILLISECONDS);\n        assertThat(server.getLastMessageSend().getType(), is(TRANSACTION));\n\n        // assertThat(server.getLastMessageRcvd().getType(), is(COMPLETED));\n\n        // assertThat(Response.parseFrom(server.getLastMessageRcvd().getPayload()).getMessage(),\n        // is(\"OK response2\"));\n    }\n\n    @Test\n    void testStateValidationParameter() throws Exception {\n        final ChaincodeBase cb = new ChaincodeBase() {\n            @Override\n            public Response init(final ChaincodeStub stub) {\n                return ResponseUtils.newSuccessResponse(\"OK response1\");\n            }\n\n            @Override\n            public Response invoke(final ChaincodeStub stub) {\n                final String aKey = stub.getStringArgs().get(1);\n                final byte[] epBytes = stub.getStateValidationParameter(aKey);\n                final StateBasedEndorsement stateBasedEndorsement =\n                        StateBasedEndorsementFactory.getInstance().newStateBasedEndorsement(epBytes);\n                assertThat(stateBasedEndorsement.listOrgs().size(), is(2));\n                stub.setStateValidationParameter(aKey, stateBasedEndorsement.policy());\n                return ResponseUtils.newSuccessResponse(\"OK response2\");\n            }\n        };\n\n        final ByteString initPayload = ChaincodeInput.newBuilder()\n                .addArgs(ByteString.copyFromUtf8(\"init\"))\n                .build()\n                .toByteString();\n        final ChaincodeMessage initMsg = MessageUtil.newEventMessage(INIT, \"testChannel\", \"0\", initPayload, null);\n\n        final StateBasedEndorsement sbe =\n                StateBasedEndorsementFactory.getInstance().newStateBasedEndorsement(null);\n        sbe.addOrgs(StateBasedEndorsement.RoleType.RoleTypePeer, \"Org1\");\n        sbe.addOrgs(StateBasedEndorsement.RoleType.RoleTypeMember, \"Org2\");\n\n        final List<ScenarioStep> scenario = new ArrayList<>();\n        scenario.add(new RegisterStep());\n        scenario.add(new CompleteStep());\n\n        scenario.add(new GetStateMetadata(sbe));\n        scenario.add(new PutStateMetadata(sbe));\n        scenario.add(new CompleteStep());\n\n        setLogLevel(\"DEBUG\");\n        server = ChaincodeMockPeer.startServer(scenario);\n\n        cb.start(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 1, 5000, TimeUnit.MILLISECONDS);\n\n        server.send(initMsg);\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 2, 5000, TimeUnit.MILLISECONDS);\n\n        assertThat(server.getLastMessageSend().getType(), is(INIT));\n        assertThat(server.getLastMessageRcvd().getType(), is(COMPLETED));\n        assertThat(Response.parseFrom(server.getLastMessageRcvd().getPayload()).getMessage(), is(\"OK response1\"));\n\n        final ByteString invokePayload = ChaincodeInput.newBuilder()\n                .addArgs(ByteString.copyFromUtf8(\"invoke\"))\n                .addArgs(ByteString.copyFromUtf8(\"a\"))\n                .build()\n                .toByteString();\n        final ChaincodeMessage invokeMsg =\n                MessageUtil.newEventMessage(TRANSACTION, \"testChannel\", \"0\", invokePayload, null);\n\n        server.send(invokeMsg);\n\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 5, 5000, TimeUnit.MILLISECONDS);\n        assertThat(server.getLastMessageSend().getType(), is(RESPONSE));\n        assertThat(server.getLastMessageRcvd().getType(), is(COMPLETED));\n        assertThat(Response.parseFrom(server.getLastMessageRcvd().getPayload()).getMessage(), is(\"OK response2\"));\n    }\n\n    @Test\n    void testInvokeRangeQ() throws Exception {\n        final ChaincodeBase cb = new ChaincodeBase() {\n            @Override\n            public Response init(final ChaincodeStub stub) {\n                return ResponseUtils.newSuccessResponse(\"OK response1\");\n            }\n\n            @Override\n            public Response invoke(final ChaincodeStub stub) {\n                assertThat(stub.getFunction(), is(\"invoke\"));\n                assertThat(stub.getArgs().size(), is(3));\n                final String aKey = stub.getStringArgs().get(1);\n                final String bKey = stub.getStringArgs().get(2);\n\n                final QueryResultsIterator<KeyValue> stateByRange = stub.getStateByRange(aKey, bKey);\n                final Iterator<KeyValue> iter = stateByRange.iterator();\n                while (iter.hasNext()) {\n                    iter.next();\n                }\n                try {\n                    stateByRange.close();\n                } catch (final Exception e) {\n                    fail(\"No exception expected\");\n                }\n                return ResponseUtils.newSuccessResponse(\"OK response2\");\n            }\n        };\n\n        final ByteString initPayload = ChaincodeInput.newBuilder()\n                .addArgs(ByteString.copyFromUtf8(\"\"))\n                .build()\n                .toByteString();\n        final ChaincodeMessage initMsg = MessageUtil.newEventMessage(INIT, \"testChannel\", \"0\", initPayload, null);\n\n        final ByteString invokePayload = ChaincodeInput.newBuilder()\n                .addArgs(ByteString.copyFromUtf8(\"invoke\"))\n                .addArgs(ByteString.copyFromUtf8(\"a\"))\n                .addArgs(ByteString.copyFromUtf8(\"b\"))\n                .build()\n                .toByteString();\n        final ChaincodeMessage invokeMsg =\n                MessageUtil.newEventMessage(TRANSACTION, \"testChannel\", \"0\", invokePayload, null);\n\n        final List<ScenarioStep> scenario = new ArrayList<>();\n        scenario.add(new RegisterStep());\n        scenario.add(new CompleteStep());\n        scenario.add(new GetStateByRangeStep(false, \"a\", \"b\"));\n        scenario.add(new QueryCloseStep());\n        scenario.add(new CompleteStep());\n        scenario.add(new GetStateByRangeStep(true, \"a\", \"b\"));\n        scenario.add(new QueryNextStep(false, \"c\"));\n        scenario.add(new QueryCloseStep());\n        scenario.add(new CompleteStep());\n\n        setLogLevel(\"DEBUG\");\n        server = ChaincodeMockPeer.startServer(scenario);\n\n        cb.start(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 1, 5000, TimeUnit.MILLISECONDS);\n\n        server.send(initMsg);\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 2, 5000, TimeUnit.MILLISECONDS);\n\n        server.send(invokeMsg);\n\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 5, 5000, TimeUnit.MILLISECONDS);\n        assertThat(server.getLastMessageSend().getType(), is(RESPONSE));\n        assertThat(server.getLastMessageRcvd().getType(), is(COMPLETED));\n        assertThat(Response.parseFrom(server.getLastMessageRcvd().getPayload()).getMessage(), is(\"OK response2\"));\n\n        server.send(invokeMsg);\n\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 9, 30000, TimeUnit.MILLISECONDS);\n        assertThat(server.getLastMessageSend().getType(), is(RESPONSE));\n        assertThat(server.getLastMessageRcvd().getType(), is(COMPLETED));\n        assertThat(Response.parseFrom(server.getLastMessageRcvd().getPayload()).getMessage(), is(\"OK response2\"));\n    }\n\n    @Test\n    void testGetQueryResult() throws Exception {\n        final ChaincodeBase cb = new ChaincodeBase() {\n            @Override\n            public Response init(final ChaincodeStub stub) {\n                return ResponseUtils.newSuccessResponse(\"OK response1\");\n            }\n\n            @Override\n            public Response invoke(final ChaincodeStub stub) {\n                final String query = stub.getStringArgs().get(1);\n\n                final QueryResultsIterator<KeyValue> queryResult = stub.getQueryResult(query);\n                final Iterator<KeyValue> iter = queryResult.iterator();\n                while (iter.hasNext()) {\n                    iter.next();\n                }\n                try {\n                    queryResult.close();\n                } catch (final Exception e) {\n                    fail(\"No exception expected\");\n                }\n                return ResponseUtils.newSuccessResponse(\"OK response2\");\n            }\n        };\n\n        final ByteString initPayload = ChaincodeInput.newBuilder()\n                .addArgs(ByteString.copyFromUtf8(\"\"))\n                .build()\n                .toByteString();\n        final ChaincodeMessage initMsg = MessageUtil.newEventMessage(INIT, \"testChannel\", \"0\", initPayload, null);\n\n        final ByteString invokePayload = ChaincodeInput.newBuilder()\n                .addArgs(ByteString.copyFromUtf8(\"invoke\"))\n                .addArgs(ByteString.copyFromUtf8(\"query\"))\n                .build()\n                .toByteString();\n        final ChaincodeMessage invokeMsg =\n                MessageUtil.newEventMessage(TRANSACTION, \"testChannel\", \"0\", invokePayload, null);\n\n        final List<ScenarioStep> scenario = new ArrayList<>();\n        scenario.add(new RegisterStep());\n        scenario.add(new CompleteStep());\n        scenario.add(new GetQueryResultStep(false, \"a\", \"b\"));\n        scenario.add(new QueryCloseStep());\n        scenario.add(new CompleteStep());\n        scenario.add(new GetQueryResultStep(true, \"a\", \"b\"));\n        scenario.add(new QueryNextStep(false, \"c\"));\n        scenario.add(new QueryCloseStep());\n        scenario.add(new CompleteStep());\n\n        setLogLevel(\"DEBUG\");\n        server = ChaincodeMockPeer.startServer(scenario);\n\n        cb.start(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 1, 5000, TimeUnit.MILLISECONDS);\n\n        server.send(initMsg);\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 2, 5000, TimeUnit.MILLISECONDS);\n\n        server.send(invokeMsg);\n\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 5, 5000, TimeUnit.MILLISECONDS);\n        assertThat(server.getLastMessageSend().getType(), is(RESPONSE));\n        assertThat(server.getLastMessageRcvd().getType(), is(COMPLETED));\n        assertThat(Response.parseFrom(server.getLastMessageRcvd().getPayload()).getMessage(), is(\"OK response2\"));\n\n        server.send(invokeMsg);\n\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 9, 5000, TimeUnit.MILLISECONDS);\n        assertThat(server.getLastMessageSend().getType(), is(RESPONSE));\n        assertThat(server.getLastMessageRcvd().getType(), is(COMPLETED));\n        assertThat(Response.parseFrom(server.getLastMessageRcvd().getPayload()).getMessage(), is(\"OK response2\"));\n    }\n\n    @Test\n    void testGetHistoryForKey() throws Exception {\n        final ChaincodeBase cb = new ChaincodeBase() {\n            @Override\n            public Response init(final ChaincodeStub stub) {\n                return ResponseUtils.newSuccessResponse(\"OK response1\");\n            }\n\n            @Override\n            public Response invoke(final ChaincodeStub stub) {\n                final String key = stub.getStringArgs().get(1);\n\n                final QueryResultsIterator<KeyModification> queryResult = stub.getHistoryForKey(key);\n                final Iterator<KeyModification> iter = queryResult.iterator();\n                while (iter.hasNext()) {\n                    iter.next();\n                }\n                try {\n                    queryResult.close();\n                } catch (final Exception e) {\n                    fail(\"No exception expected\");\n                }\n                return ResponseUtils.newSuccessResponse(\"OK response2\");\n            }\n        };\n\n        final ByteString initPayload = ChaincodeInput.newBuilder()\n                .addArgs(ByteString.copyFromUtf8(\"\"))\n                .build()\n                .toByteString();\n        final ChaincodeMessage initMsg = MessageUtil.newEventMessage(INIT, \"testChannel\", \"0\", initPayload, null);\n\n        final ByteString invokePayload = ChaincodeInput.newBuilder()\n                .addArgs(ByteString.copyFromUtf8(\"invoke\"))\n                .addArgs(ByteString.copyFromUtf8(\"key1\"))\n                .build()\n                .toByteString();\n        final ChaincodeMessage invokeMsg =\n                MessageUtil.newEventMessage(TRANSACTION, \"testChannel\", \"0\", invokePayload, null);\n\n        final List<ScenarioStep> scenario = new ArrayList<>();\n        scenario.add(new RegisterStep());\n        scenario.add(new CompleteStep());\n        scenario.add(new GetHistoryForKeyStep(false, \"1\", \"2\"));\n        scenario.add(new QueryCloseStep());\n        scenario.add(new CompleteStep());\n\n        setLogLevel(\"DEBUG\");\n        server = ChaincodeMockPeer.startServer(scenario);\n\n        cb.start(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 1, 5000, TimeUnit.MILLISECONDS);\n\n        server.send(initMsg);\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 2, 5000, TimeUnit.MILLISECONDS);\n\n        server.send(invokeMsg);\n\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 5, 5000, TimeUnit.MILLISECONDS);\n        assertThat(server.getLastMessageSend().getType(), is(RESPONSE));\n        assertThat(server.getLastMessageRcvd().getType(), is(COMPLETED));\n        assertThat(Response.parseFrom(server.getLastMessageRcvd().getPayload()).getMessage(), is(\"OK response2\"));\n    }\n\n    @Test\n    void testInvokeChaincode() throws Exception {\n        final ChaincodeBase cb = new ChaincodeBase() {\n            @Override\n            public Response init(final ChaincodeStub stub) {\n                return ResponseUtils.newSuccessResponse(\"OK response1\");\n            }\n\n            @Override\n            public Response invoke(final ChaincodeStub stub) {\n                stub.invokeChaincode(\"anotherChaincode\", Collections.emptyList());\n                return ResponseUtils.newSuccessResponse(\"OK response2\");\n            }\n        };\n\n        final ByteString initPayload = ChaincodeInput.newBuilder()\n                .addArgs(ByteString.copyFromUtf8(\"\"))\n                .build()\n                .toByteString();\n        final ChaincodeMessage initMsg = MessageUtil.newEventMessage(INIT, \"testChannel\", \"0\", initPayload, null);\n\n        final ByteString invokePayload = ChaincodeInput.newBuilder()\n                .addArgs(ByteString.copyFromUtf8(\"invoke\"))\n                .build()\n                .toByteString();\n        final ChaincodeMessage invokeMsg =\n                MessageUtil.newEventMessage(TRANSACTION, \"testChannel\", \"0\", invokePayload, null);\n\n        final List<ScenarioStep> scenario = new ArrayList<>();\n        scenario.add(new RegisterStep());\n        scenario.add(new CompleteStep());\n        scenario.add(new InvokeChaincodeStep());\n        scenario.add(new CompleteStep());\n\n        setLogLevel(\"DEBUG\");\n        server = ChaincodeMockPeer.startServer(scenario);\n\n        cb.start(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 1, 5000, TimeUnit.MILLISECONDS);\n\n        server.send(initMsg);\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 2, 5000, TimeUnit.MILLISECONDS);\n\n        server.send(invokeMsg);\n\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 4, 10000, TimeUnit.MILLISECONDS);\n        assertThat(server.getLastMessageSend().getType(), is(RESPONSE));\n        assertThat(server.getLastMessageRcvd().getType(), is(COMPLETED));\n    }\n\n    @Test\n    void testErrorInitInvoke() throws Exception {\n        final ChaincodeBase cb = new ChaincodeBase() {\n            @Override\n            public Response init(final ChaincodeStub stub) {\n                return ResponseUtils.newErrorResponse(\"Wrong response1\".getBytes());\n            }\n\n            @Override\n            public Response invoke(final ChaincodeStub stub) {\n                return ResponseUtils.newErrorResponse(\"Wrong response2\");\n            }\n        };\n\n        final ByteString payload = ChaincodeInput.newBuilder()\n                .addArgs(ByteString.copyFromUtf8(\"\"))\n                .build()\n                .toByteString();\n        final ChaincodeMessage initMsg = MessageUtil.newEventMessage(INIT, \"testChannel\", \"0\", payload, null);\n\n        final List<ScenarioStep> scenario = new ArrayList<>();\n        scenario.add(new RegisterStep());\n        scenario.add(new ErrorResponseStep());\n        scenario.add(new ErrorResponseStep());\n\n        setLogLevel(\"DEBUG\");\n        server = ChaincodeMockPeer.startServer(scenario);\n\n        cb.start(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 1, 5000, TimeUnit.MILLISECONDS);\n\n        server.send(initMsg);\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 2, 5000, TimeUnit.MILLISECONDS);\n\n        assertThat(server.getLastMessageSend().getType(), is(INIT));\n        assertThat(server.getLastMessageRcvd().getType(), is(COMPLETED));\n        String resp1 = Response.parseFrom(server.getLastMessageRcvd().getPayload())\n                .getPayload()\n                .toStringUtf8();\n        assertThat(resp1, is(\"Wrong response1\"));\n\n        final ByteString invokePayload = ChaincodeInput.newBuilder().build().toByteString();\n        final ChaincodeMessage invokeMsg =\n                MessageUtil.newEventMessage(TRANSACTION, \"testChannel\", \"0\", invokePayload, null);\n\n        server.send(invokeMsg);\n\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 3, 5000, TimeUnit.MILLISECONDS);\n        assertThat(server.getLastMessageSend().getType(), is(TRANSACTION));\n        assertThat(server.getLastMessageRcvd().getType(), is(COMPLETED));\n        String resp2 = Response.parseFrom(server.getLastMessageRcvd().getPayload())\n                .getMessage()\n                .toString();\n        assertThat(resp2, is(\"Wrong response2\"));\n    }\n\n    @Test\n    void testStreamShutdown() throws Exception {\n        final ChaincodeBase cb = new ChaincodeBase() {\n            @Override\n            public Response init(final ChaincodeStub stub) {\n                try {\n                    Thread.sleep(10);\n                } catch (final InterruptedException ignored) {\n                }\n                return ResponseUtils.newSuccessResponse();\n            }\n\n            @Override\n            public Response invoke(final ChaincodeStub stub) {\n                return ResponseUtils.newSuccessResponse();\n            }\n        };\n\n        final ByteString payload = ChaincodeInput.newBuilder()\n                .addArgs(ByteString.copyFromUtf8(\"\"))\n                .build()\n                .toByteString();\n        final ChaincodeMessage initMsg = MessageUtil.newEventMessage(INIT, \"testChannel\", \"0\", payload, null);\n\n        final List<ScenarioStep> scenario = new ArrayList<>();\n        scenario.add(new RegisterStep());\n        scenario.add(new CompleteStep());\n\n        setLogLevel(\"DEBUG\");\n        server = ChaincodeMockPeer.startServer(scenario);\n\n        cb.start(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n        ChaincodeMockPeer.checkScenarioStepEnded(server, 1, 5000, TimeUnit.MILLISECONDS);\n        server.send(initMsg);\n        server.stop();\n        server = null;\n    }\n\n    @Test\n    void testChaincodeLogLevel() throws Exception {\n        final ChaincodeBase cb = new EmptyChaincode();\n\n        final List<ScenarioStep> scenario = new ArrayList<>();\n        scenario.add(new RegisterStep());\n        scenario.add(new CompleteStep());\n\n        setLogLevel(\"DEBUG\");\n        server = ChaincodeMockPeer.startServer(scenario);\n\n        cb.start(new String[] {\"-a\", \"127.0.0.1:7052\", \"-i\", \"testId\"});\n\n        assertEquals(\n                Level.FINEST,\n                Logger.getLogger(cb.getClass().getPackage().getName()).getLevel(),\n                \"Wrong debug level for \" + cb.getClass().getPackage().getName());\n    }\n\n    private void setLogLevel(final String logLevel) {\n        environmentVariables.set(\"CORE_CHAINCODE_LOGGING_SHIM\", logLevel);\n        environmentVariables.set(\"CORE_CHAINCODE_LOGGING_LEVEL\", logLevel);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/impl/ChaincodeMessageFactoryTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.impl;\n\nimport com.google.protobuf.ByteString;\nimport org.hyperledger.fabric.protos.peer.ChaincodeEvent;\nimport org.hyperledger.fabric.protos.peer.ChaincodeID;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type;\nimport org.hyperledger.fabric.shim.Chaincode.Response;\nimport org.hyperledger.fabric.shim.ResponseUtils;\nimport org.junit.jupiter.api.Test;\n\nfinal class ChaincodeMessageFactoryTest {\n\n    private final String txId = \"txid\";\n    private final String key = \"key\";\n    private final String channelId = \"channelid\";\n    private final String collection = \"collectionId\";\n    private final ByteString value = ByteString.copyFromUtf8(\"Hello\");\n    private final String metakey = \"metakey\";\n    private final Throwable throwable = new Throwable();\n    private final String message = \"message\";\n    private ChaincodeEvent event;\n    private final Response response = ResponseUtils.newSuccessResponse();\n    private final ByteString payload = ByteString.copyFromUtf8(\"Hello\");\n    private final ChaincodeID chaincodeId =\n            ChaincodeID.newBuilder().setName(\"test\").build();\n    private final Type type = ChaincodeMessage.Type.COMPLETED;\n\n    @Test\n    void testNewGetPrivateDataHashEventMessage() {\n        ChaincodeMessageFactory.newGetPrivateDataHashEventMessage(channelId, txId, collection, key);\n    }\n\n    @Test\n    void testNewGetStateEventMessage() {\n        ChaincodeMessageFactory.newGetStateEventMessage(channelId, txId, collection, key);\n    }\n\n    @Test\n    void testNewGetStateMetadataEventMessage() {\n        ChaincodeMessageFactory.newGetStateMetadataEventMessage(channelId, txId, collection, key);\n    }\n\n    @Test\n    void testNewPutStateEventMessage() {\n        ChaincodeMessageFactory.newPutStateEventMessage(channelId, txId, collection, key, value);\n    }\n\n    @Test\n    void testNewPutStateMetadataEventMessage() {\n        ChaincodeMessageFactory.newPutStateMetadataEventMessage(channelId, txId, collection, key, metakey, value);\n    }\n\n    @Test\n    void testNewDeleteStateEventMessage() {\n        ChaincodeMessageFactory.newDeleteStateEventMessage(channelId, txId, collection, key);\n    }\n\n    @Test\n    void testNewErrorEventMessage() {\n        ChaincodeMessageFactory.newErrorEventMessage(channelId, txId, message);\n        ChaincodeMessageFactory.newErrorEventMessage(channelId, txId, throwable);\n        ChaincodeMessageFactory.newErrorEventMessage(channelId, txId, message, event);\n    }\n\n    @Test\n    void testNewCompletedEventMessage() {\n\n        ChaincodeMessageFactory.newCompletedEventMessage(channelId, txId, response, event);\n    }\n\n    @Test\n    void testNewInvokeChaincodeMessage() {\n        ChaincodeMessageFactory.newInvokeChaincodeMessage(channelId, txId, payload);\n    }\n\n    @Test\n    void testNewRegisterChaincodeMessage() {\n        ChaincodeMessageFactory.newRegisterChaincodeMessage(chaincodeId);\n    }\n\n    @Test\n    void testNewEventMessageTypeStringStringByteString() {\n        ChaincodeMessageFactory.newEventMessage(type, channelId, txId, payload);\n        ChaincodeMessageFactory.newEventMessage(type, channelId, txId, payload, event);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/impl/ChaincodeSupportClientTest.java",
    "content": "/*\n * Copyright 2020 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.impl;\n\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\n\nimport io.grpc.ManagedChannelBuilder;\nimport io.grpc.stub.StreamObserver;\nimport java.io.IOException;\nimport java.util.Properties;\nimport org.hyperledger.fabric.metrics.Metrics;\nimport org.hyperledger.fabric.protos.peer.ChaincodeID;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.shim.ChaincodeBase;\nimport org.hyperledger.fabric.shim.chaincode.EmptyChaincode;\nimport org.hyperledger.fabric.traces.Traces;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport uk.org.webcompere.systemstubs.environment.EnvironmentVariables;\nimport uk.org.webcompere.systemstubs.jupiter.SystemStub;\nimport uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension;\n\n@ExtendWith(SystemStubsExtension.class)\nfinal class ChaincodeSupportClientTest {\n    @SystemStub\n    private final EnvironmentVariables environmentVariables = new EnvironmentVariables();\n\n    @Test\n    void testStartInvocationTaskManagerAndRequestObserverNull() throws IOException {\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"mycc\");\n        final ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n        chaincodeBase.validateOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Metrics.initialize(props);\n        Traces.initialize(props);\n\n        final ManagedChannelBuilder<?> managedChannelBuilder = chaincodeBase.newChannelBuilder();\n        ChaincodeSupportClient chaincodeSupportClient = new ChaincodeSupportClient(managedChannelBuilder);\n\n        assertThatThrownBy(\n                        () -> {\n                            final ChaincodeID chaincodeId = ChaincodeID.newBuilder()\n                                    .setName(\"chaincodeIdNumber12345\")\n                                    .build();\n                            final InvocationTaskManager itm =\n                                    InvocationTaskManager.getManager(chaincodeBase, chaincodeId);\n\n                            final StreamObserver<ChaincodeMessage> requestObserver = null;\n                            chaincodeSupportClient.start(itm, requestObserver);\n                        },\n                        \"StreamObserver 'requestObserver' for chat with peer can't be null\")\n                .isInstanceOf(IOException.class);\n        environmentVariables.remove(\"CORE_CHAINCODE_ID_NAME\");\n    }\n\n    @Test\n    void testStartInvocationTaskManagerNullAndRequestObserver() throws IOException {\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"mycc\");\n        final ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n        chaincodeBase.validateOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Metrics.initialize(props);\n        Traces.initialize(props);\n\n        final ManagedChannelBuilder<?> managedChannelBuilder = chaincodeBase.newChannelBuilder();\n        ChaincodeSupportClient chaincodeSupportClient = new ChaincodeSupportClient(managedChannelBuilder);\n\n        assertThatThrownBy(\n                        () -> {\n                            chaincodeSupportClient.start(null, new StreamObserver<>() {\n                                @Override\n                                public void onNext(final ChaincodeMessage value) {}\n\n                                @Override\n                                public void onError(final Throwable t) {}\n\n                                @Override\n                                public void onCompleted() {}\n                            });\n                        },\n                        \"InvocationTaskManager 'itm' can't be null\")\n                .isInstanceOf(IOException.class);\n        environmentVariables.remove(\"CORE_CHAINCODE_ID_NAME\");\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/impl/InnvocationTaskManagerTest.java",
    "content": "/*\n * Copyright 2020 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.impl;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.google.protobuf.ByteString;\nimport io.grpc.ManagedChannelBuilder;\nimport java.io.IOException;\nimport java.util.Properties;\nimport java.util.function.Consumer;\nimport org.hyperledger.fabric.metrics.Metrics;\nimport org.hyperledger.fabric.protos.peer.ChaincodeID;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.shim.ChaincodeBase;\nimport org.hyperledger.fabric.shim.chaincode.EmptyChaincode;\nimport org.hyperledger.fabric.traces.Traces;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport uk.org.webcompere.systemstubs.environment.EnvironmentVariables;\nimport uk.org.webcompere.systemstubs.jupiter.SystemStub;\nimport uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension;\n\n@ExtendWith(SystemStubsExtension.class)\nfinal class InnvocationTaskManagerTest {\n    @SystemStub\n    private final EnvironmentVariables environmentVariables = new EnvironmentVariables();\n\n    @BeforeEach\n    void setEnv() {\n        environmentVariables.set(\"CORE_CHAINCODE_ID_NAME\", \"mycc\");\n        environmentVariables.set(\"CORE_PEER_ADDRESS\", \"localhost:7052\");\n        environmentVariables.set(\"CORE_PEER_TLS_ENABLED\", \"false\");\n        environmentVariables.set(\"CORE_PEER_TLS_ROOTCERT_FILE\", \"src/test/resources/ca.crt\");\n        environmentVariables.set(\"CORE_TLS_CLIENT_KEY_PATH\", \"src/test/resources/client.key.enc\");\n        environmentVariables.set(\"CORE_TLS_CLIENT_CERT_PATH\", \"src/test/resources/client.crt.enc\");\n    }\n\n    @AfterEach\n    void clearEnv() {\n        environmentVariables.remove(\"CORE_CHAINCODE_ID_NAME\");\n        environmentVariables.remove(\"CORE_PEER_ADDRESS\");\n        environmentVariables.remove(\"CORE_PEER_TLS_ENABLED\");\n        environmentVariables.remove(\"CORE_PEER_TLS_ROOTCERT_FILE\");\n        environmentVariables.remove(\"CORE_TLS_CLIENT_KEY_PATH\");\n        environmentVariables.remove(\"CORE_TLS_CLIENT_CERT_PATH\");\n    }\n\n    @Test\n    void getManager() throws IOException {\n\n        final ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n        chaincodeBase.validateOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Traces.initialize(props);\n        Metrics.initialize(props);\n\n        final ChaincodeID chaincodeId =\n                ChaincodeID.newBuilder().setName(\"chaincodeIdNumber12345\").build();\n        final InvocationTaskManager itm = InvocationTaskManager.getManager(chaincodeBase, chaincodeId);\n    }\n\n    @Test\n    void getManagerChaincodeIDNull() throws IOException {\n\n        final ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n        chaincodeBase.validateOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Metrics.initialize(props);\n        Traces.initialize(props);\n\n        Assertions.assertThrows(\n                IllegalArgumentException.class,\n                () -> {\n                    final InvocationTaskManager itm = InvocationTaskManager.getManager(chaincodeBase, null);\n                },\n                \"chaincodeId can't be null\");\n    }\n\n    @Test\n    void getManagerChaincodeBaseNull() throws IOException {\n\n        final ChaincodeID chaincodeId =\n                ChaincodeID.newBuilder().setName(\"chaincodeIdNumber12345\").build();\n\n        Assertions.assertThrows(\n                IllegalArgumentException.class,\n                () -> {\n                    final InvocationTaskManager itm = InvocationTaskManager.getManager(null, chaincodeId);\n                },\n                \"chaincode is null\");\n    }\n\n    @Test\n    void onChaincodeMessage() throws IOException {\n\n        final ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n        chaincodeBase.validateOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Metrics.initialize(props);\n        Traces.initialize(props);\n\n        final ChaincodeID chaincodeId =\n                ChaincodeID.newBuilder().setName(\"chaincodeIdNumber12345\").build();\n        final InvocationTaskManager itm = InvocationTaskManager.getManager(chaincodeBase, chaincodeId);\n\n        Assertions.assertThrows(\n                IllegalArgumentException.class, () -> itm.onChaincodeMessage(null), \"chaincodeMessage is null\");\n    }\n\n    @Test\n    void setResponseConsumer() throws IOException {\n\n        final ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n        chaincodeBase.validateOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Metrics.initialize(props);\n        Traces.initialize(props);\n\n        final ChaincodeID chaincodeId =\n                ChaincodeID.newBuilder().setName(\"chaincodeIdNumber12345\").build();\n        final InvocationTaskManager itm = InvocationTaskManager.getManager(chaincodeBase, chaincodeId);\n        itm.setResponseConsumer(null);\n    }\n\n    @Test\n    void registerException() {\n\n        final ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n        chaincodeBase.validateOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Metrics.initialize(props);\n        Traces.initialize(props);\n\n        final ChaincodeID chaincodeId =\n                ChaincodeID.newBuilder().setName(\"chaincodeIdNumber12345\").build();\n        final InvocationTaskManager itm = InvocationTaskManager.getManager(chaincodeBase, chaincodeId);\n\n        Assertions.assertThrows(IllegalArgumentException.class, itm::register, \"outgoingMessage is null\");\n    }\n\n    @Test\n    void onChaincodeMessageREGISTER() {\n\n        final ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n        chaincodeBase.validateOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Metrics.initialize(props);\n        Traces.initialize(props);\n\n        final ChaincodeID chaincodeId =\n                ChaincodeID.newBuilder().setName(\"chaincodeIdNumber12345\").build();\n        final InvocationTaskManager itm = InvocationTaskManager.getManager(chaincodeBase, chaincodeId);\n        final Consumer<ChaincodeMessage> consumer = t -> {\n            assertEquals(ChaincodeMessageFactory.newRegisterChaincodeMessage(chaincodeId), t);\n        };\n\n        itm.setResponseConsumer(consumer);\n        final ChaincodeMessage chaincodeMessage = ChaincodeMessageFactory.newRegisterChaincodeMessage(chaincodeId);\n        itm.onChaincodeMessage(chaincodeMessage);\n    }\n\n    @Test\n    void onChaincodeMessageInvokeChaincode() {\n\n        final ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n        chaincodeBase.validateOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Metrics.initialize(props);\n        Traces.initialize(props);\n\n        final String chaincodeIdNumber = \"chaincodeIdNumber12345\";\n        final ChaincodeID chaincodeId =\n                ChaincodeID.newBuilder().setName(chaincodeIdNumber).build();\n        final InvocationTaskManager itm = InvocationTaskManager.getManager(chaincodeBase, chaincodeId);\n        final Consumer<ChaincodeMessage> consumer = t -> {\n            assertEquals(ChaincodeMessageFactory.newRegisterChaincodeMessage(chaincodeId), t);\n        };\n\n        itm.setResponseConsumer(consumer);\n        final ChaincodeMessage chaincodeMessage = ChaincodeMessageFactory.newInvokeChaincodeMessage(\n                chaincodeIdNumber, \"txid\", ByteString.copyFromUtf8(\"\"));\n        itm.onChaincodeMessage(chaincodeMessage);\n    }\n\n    @Test\n    void onChaincodeMessagePutState() {\n\n        final ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n        chaincodeBase.validateOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Metrics.initialize(props);\n        Traces.initialize(props);\n\n        final String chaincodeIdNumber = \"chaincodeIdNumber12345\";\n        final ChaincodeID chaincodeId =\n                ChaincodeID.newBuilder().setName(chaincodeIdNumber).build();\n        final InvocationTaskManager itm = InvocationTaskManager.getManager(chaincodeBase, chaincodeId);\n        final Consumer<ChaincodeMessage> consumer = t -> {\n            assertEquals(ChaincodeMessageFactory.newRegisterChaincodeMessage(chaincodeId), t);\n        };\n\n        itm.setResponseConsumer(consumer);\n        final ChaincodeMessage chaincodeMessage = ChaincodeMessageFactory.newPutStateEventMessage(\n                chaincodeIdNumber, \"txid\", \"collection\", \"key\", ByteString.copyFromUtf8(\"value\"));\n        itm.onChaincodeMessage(chaincodeMessage);\n    }\n\n    @Test\n    void shutdown() throws IOException {\n\n        final ChaincodeBase chaincodeBase = new EmptyChaincode();\n        chaincodeBase.processEnvironmentOptions();\n        chaincodeBase.validateOptions();\n\n        Properties props = chaincodeBase.getChaincodeConfig();\n        Traces.initialize(props);\n        Metrics.initialize(props);\n\n        final ManagedChannelBuilder<?> managedChannelBuilder = chaincodeBase.newChannelBuilder();\n        ChaincodeSupportClient chaincodeSupportClient = new ChaincodeSupportClient(managedChannelBuilder);\n\n        final ChaincodeID chaincodeId =\n                ChaincodeID.newBuilder().setName(\"chaincodeIdNumber12345\").build();\n        final InvocationTaskManager itm = InvocationTaskManager.getManager(chaincodeBase, chaincodeId);\n        itm.shutdown();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/impl/InvocationStubImplTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.impl;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.GET_STATE_BY_RANGE;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\nimport com.google.protobuf.ByteString;\nimport com.google.protobuf.InvalidProtocolBufferException;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.GetStateByRange;\nimport org.hyperledger.fabric.protos.peer.QueryResponse;\nimport org.hyperledger.fabric.shim.ledger.KeyValue;\nimport org.hyperledger.fabric.shim.ledger.QueryResultsIterator;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.ArgumentCaptor;\n\nfinal class InvocationStubImplTest {\n\n    private final String channelId = \"mychannel\";\n    private final String txId = \"0xCAFEBABE\";\n    private final String simpleKeyStartNamespace = new String(Character.toChars(0x000001));\n\n    @Nested\n    final class GetStateByRangeTests {\n\n        private InvocationStubImpl stubImpl;\n        private ArgumentCaptor<ChaincodeMessage> chaincodeMessageCaptor;\n        private ChaincodeInvocationTask mockHandler;\n\n        @BeforeEach\n        void beforeEach() throws Exception {\n            final ChaincodeMessage mockMessage =\n                    ChaincodeMessageFactory.newGetStateEventMessage(channelId, txId, \"\", \"key\");\n            mockHandler = mock(ChaincodeInvocationTask.class);\n            final ByteString mockString = QueryResponse.newBuilder().build().toByteString();\n\n            chaincodeMessageCaptor = ArgumentCaptor.forClass(ChaincodeMessage.class);\n\n            when(mockHandler.invoke(any())).thenReturn(mockString);\n            stubImpl = new InvocationStubImpl(mockMessage, mockHandler);\n        }\n\n        @Test\n        void regular() throws InvalidProtocolBufferException {\n            final QueryResultsIterator<KeyValue> qri = stubImpl.getStateByRange(\"Aardvark\", \"Zebra\");\n\n            verify(mockHandler).invoke(chaincodeMessageCaptor.capture());\n            assertThat(qri).isNotNull();\n\n            final ChaincodeMessage msg = chaincodeMessageCaptor.getValue();\n            assertThat(msg.getTxid()).isEqualTo(\"0xCAFEBABE\");\n            assertThat(msg.getType()).isEqualTo(GET_STATE_BY_RANGE);\n\n            final GetStateByRange range = GetStateByRange.parseFrom(msg.getPayload());\n            assertThat(range.getStartKey()).isEqualTo(\"Aardvark\");\n            assertThat(range.getEndKey()).isEqualTo(\"Zebra\");\n        }\n\n        @Test\n        void nullvalues() throws InvalidProtocolBufferException {\n            final QueryResultsIterator<KeyValue> qri = stubImpl.getStateByRange(null, null);\n\n            verify(mockHandler).invoke(chaincodeMessageCaptor.capture());\n            assertThat(qri).isNotNull();\n\n            final ChaincodeMessage msg = chaincodeMessageCaptor.getValue();\n            assertThat(msg.getTxid()).isEqualTo(\"0xCAFEBABE\");\n            assertThat(msg.getType()).isEqualTo(GET_STATE_BY_RANGE);\n\n            final GetStateByRange range = GetStateByRange.parseFrom(msg.getPayload());\n\n            assertThat(range.getStartKey()).isEqualTo(simpleKeyStartNamespace);\n            assertThat(range.getEndKey()).isEqualTo(\"\");\n        }\n\n        @Test\n        void unbounded() throws InvalidProtocolBufferException {\n            final QueryResultsIterator<KeyValue> qri = stubImpl.getStateByRange(\"\", \"\");\n\n            verify(mockHandler).invoke(chaincodeMessageCaptor.capture());\n            assertThat(qri).isNotNull();\n\n            final ChaincodeMessage msg = chaincodeMessageCaptor.getValue();\n            assertThat(msg.getTxid()).isEqualTo(\"0xCAFEBABE\");\n            assertThat(msg.getType()).isEqualTo(GET_STATE_BY_RANGE);\n\n            final GetStateByRange range = GetStateByRange.parseFrom(msg.getPayload());\n\n            assertThat(range.getStartKey()).isEqualTo(simpleKeyStartNamespace);\n            assertThat(range.getEndKey()).isEqualTo(\"\");\n        }\n\n        @Test\n        void simplekeys() {\n            assertThatThrownBy(() -> {\n                        final QueryResultsIterator<KeyValue> qri =\n                                stubImpl.getStateByRange(new String(Character.toChars(Character.MIN_CODE_POINT)), \"\");\n                    })\n                    .hasMessageContaining(\"not allowed\");\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/impl/InvocationTaskManagerTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.impl;\n\nimport static org.mockito.Mockito.when;\n\nimport com.google.protobuf.ByteString;\nimport java.io.UnsupportedEncodingException;\nimport java.util.Properties;\nimport java.util.logging.Level;\nimport java.util.logging.LogManager;\nimport java.util.logging.Logger;\nimport org.hyperledger.fabric.metrics.Metrics;\nimport org.hyperledger.fabric.protos.peer.ChaincodeID;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.shim.ChaincodeBase;\nimport org.hyperledger.fabric.traces.Traces;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\n\nfinal class InvocationTaskManagerTest {\n\n    private InvocationTaskManager itm;\n    private ChaincodeBase chaincode;\n    private Logger perfLogger;\n\n    @BeforeEach\n    void setup() {\n        Metrics.initialize(new Properties());\n        Traces.initialize(new Properties());\n\n        chaincode = Mockito.mock(ChaincodeBase.class);\n        final ChaincodeID id = ChaincodeID.newBuilder().setName(\"randomname\").build();\n        when(chaincode.getChaincodeConfig()).thenReturn(new Properties());\n        this.itm = InvocationTaskManager.getManager(chaincode, id);\n\n        perfLogger = LogManager.getLogManager().getLogger(\"org.hyperledger.Performance\");\n        perfLogger.setLevel(Level.ALL);\n        this.itm.setResponseConsumer((value) -> {});\n    }\n\n    @AfterEach\n    void teardown() {\n\n        itm.shutdown();\n        perfLogger.setLevel(Level.INFO);\n    }\n\n    @Test\n    void register() throws UnsupportedEncodingException {\n        itm.register();\n    }\n\n    @Test\n    void onMessageTestTx() throws UnsupportedEncodingException {\n\n        final ChaincodeMessage msg = ChaincodeMessageFactory.newEventMessage(\n                ChaincodeMessage.Type.TRANSACTION, \"mychannel\", \"txid\", ByteString.copyFrom(\"Hello\", \"UTF-8\"));\n\n        when(chaincode.getState()).thenReturn(ChaincodeBase.CCState.READY);\n\n        itm.onChaincodeMessage(msg);\n    }\n\n    @Test\n    void onWrongCreatedState() throws UnsupportedEncodingException {\n\n        perfLogger.setLevel(Level.ALL);\n        final ChaincodeMessage msg = ChaincodeMessageFactory.newEventMessage(\n                ChaincodeMessage.Type.TRANSACTION, \"mychannel\", \"txid\", ByteString.copyFrom(\"Hello\", \"UTF-8\"));\n\n        when(chaincode.getState()).thenReturn(ChaincodeBase.CCState.CREATED);\n\n        itm.onChaincodeMessage(msg);\n    }\n\n    @Test\n    void onWrongEstablishedState() throws UnsupportedEncodingException {\n\n        final ChaincodeMessage msg = ChaincodeMessageFactory.newEventMessage(\n                ChaincodeMessage.Type.TRANSACTION, \"mychannel\", \"txid\", ByteString.copyFrom(\"Hello\", \"UTF-8\"));\n\n        when(chaincode.getState()).thenReturn(ChaincodeBase.CCState.ESTABLISHED);\n\n        // final InvocationTaskManager itm =\n        // InvocationTaskManager.getManager(chaincode, id);\n        itm.onChaincodeMessage(msg);\n    }\n\n    @Test\n    void onErrorResponse() throws UnsupportedEncodingException {\n\n        final ChaincodeMessage msg = ChaincodeMessageFactory.newEventMessage(\n                ChaincodeMessage.Type.ERROR, \"mychannel\", \"txid\", ByteString.copyFrom(\"Hello\", \"UTF-8\"));\n\n        when(chaincode.getState()).thenReturn(ChaincodeBase.CCState.READY);\n\n        itm.onChaincodeMessage(msg);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/impl/KeyModificationImplTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.impl;\n\nimport static java.nio.charset.StandardCharsets.UTF_8;\nimport static org.assertj.core.api.Assertions.assertThat;\n\nimport com.google.protobuf.ByteString;\nimport com.google.protobuf.Timestamp;\nimport java.util.stream.Stream;\nimport org.hyperledger.fabric.shim.ledger.KeyModification;\nimport org.junit.jupiter.api.Test;\n\nfinal class KeyModificationImplTest {\n\n    @Test\n    void testKeyModificationImpl() {\n        new KeyModificationImpl(org.hyperledger.fabric.protos.ledger.queryresult.KeyModification.newBuilder()\n                .setTxId(\"txid\")\n                .setValue(ByteString.copyFromUtf8(\"value\"))\n                .setTimestamp(Timestamp.newBuilder().setSeconds(1234567890).setNanos(123456789))\n                .setIsDelete(true)\n                .build());\n    }\n\n    @Test\n    void testGetTxId() {\n        final KeyModification km =\n                new KeyModificationImpl(org.hyperledger.fabric.protos.ledger.queryresult.KeyModification.newBuilder()\n                        .setTxId(\"txid\")\n                        .build());\n        assertThat(km.getTxId()).isEqualTo(\"txid\");\n    }\n\n    @Test\n    void testGetValue() {\n        final KeyModification km =\n                new KeyModificationImpl(org.hyperledger.fabric.protos.ledger.queryresult.KeyModification.newBuilder()\n                        .setValue(ByteString.copyFromUtf8(\"value\"))\n                        .build());\n        assertThat(km.getValue()).isEqualTo(\"value\".getBytes(UTF_8));\n    }\n\n    @Test\n    void testGetStringValue() {\n        final KeyModification km =\n                new KeyModificationImpl(org.hyperledger.fabric.protos.ledger.queryresult.KeyModification.newBuilder()\n                        .setValue(ByteString.copyFromUtf8(\"value\"))\n                        .build());\n        assertThat(km.getStringValue()).isEqualTo(\"value\");\n    }\n\n    @Test\n    void testGetTimestamp() {\n        final KeyModification km =\n                new KeyModificationImpl(org.hyperledger.fabric.protos.ledger.queryresult.KeyModification.newBuilder()\n                        .setTimestamp(\n                                Timestamp.newBuilder().setSeconds(1234567890L).setNanos(123456789))\n                        .build());\n        assertThat(km.getTimestamp().getEpochSecond()).isEqualTo(1234567890L);\n        assertThat(km.getTimestamp().getNano()).isEqualTo(123456789);\n    }\n\n    @Test\n    void testIsDeleted() {\n        Stream.of(true, false).forEach(b -> {\n            final KeyModification km = new KeyModificationImpl(\n                    org.hyperledger.fabric.protos.ledger.queryresult.KeyModification.newBuilder()\n                            .setIsDelete(b)\n                            .build());\n            assertThat(km.isDeleted()).isEqualTo(b);\n        });\n    }\n\n    @Test\n    void testHashCode() {\n        final KeyModification km1 =\n                new KeyModificationImpl(org.hyperledger.fabric.protos.ledger.queryresult.KeyModification.newBuilder()\n                        .setIsDelete(false)\n                        .build());\n        final KeyModification km2 =\n                new KeyModificationImpl(org.hyperledger.fabric.protos.ledger.queryresult.KeyModification.newBuilder()\n                        .setIsDelete(false)\n                        .build());\n\n        assertThat(km1.hashCode()).isEqualTo(km2.hashCode());\n    }\n\n    @Test\n    void testEquals() {\n        final KeyModification km1 =\n                new KeyModificationImpl(org.hyperledger.fabric.protos.ledger.queryresult.KeyModification.newBuilder()\n                        .setIsDelete(false)\n                        .build());\n        final KeyModification km2 =\n                new KeyModificationImpl(org.hyperledger.fabric.protos.ledger.queryresult.KeyModification.newBuilder()\n                        .setIsDelete(true)\n                        .build());\n\n        final KeyModification km3 =\n                new KeyModificationImpl(org.hyperledger.fabric.protos.ledger.queryresult.KeyModification.newBuilder()\n                        .setIsDelete(false)\n                        .build());\n\n        assertThat(km1).isNotEqualTo(km2);\n        assertThat(km1).isEqualTo(km3);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/impl/KeyValueImplTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.impl;\n\nimport static java.nio.charset.StandardCharsets.UTF_8;\nimport static org.assertj.core.api.Assertions.assertThat;\n\nimport com.google.protobuf.ByteString;\nimport org.hyperledger.fabric.protos.ledger.queryresult.KV;\nimport org.junit.jupiter.api.Test;\n\nfinal class KeyValueImplTest {\n\n    @Test\n    void testKeyValueImpl() {\n        new KeyValueImpl(KV.newBuilder()\n                .setKey(\"key\")\n                .setValue(ByteString.copyFromUtf8(\"value\"))\n                .build());\n    }\n\n    @Test\n    void testGetKey() {\n        final KeyValueImpl kv = new KeyValueImpl(KV.newBuilder()\n                .setKey(\"key\")\n                .setValue(ByteString.copyFromUtf8(\"value\"))\n                .build());\n        assertThat(kv.getKey()).isEqualTo(\"key\");\n    }\n\n    @Test\n    void testGetValue() {\n        final KeyValueImpl kv = new KeyValueImpl(KV.newBuilder()\n                .setKey(\"key\")\n                .setValue(ByteString.copyFromUtf8(\"value\"))\n                .build());\n        assertThat(kv.getValue()).isEqualTo(\"value\".getBytes(UTF_8));\n    }\n\n    @Test\n    void testGetStringValue() {\n        final KeyValueImpl kv = new KeyValueImpl(KV.newBuilder()\n                .setKey(\"key\")\n                .setValue(ByteString.copyFromUtf8(\"value\"))\n                .build());\n        assertThat(kv.getStringValue()).isEqualTo(\"value\");\n    }\n\n    @Test\n    void testHashCode() {\n        final KeyValueImpl kv1 = new KeyValueImpl(KV.newBuilder().build());\n        final KeyValueImpl kv2 = new KeyValueImpl(KV.newBuilder().build());\n\n        assertThat(kv1.hashCode()).isEqualTo(kv2.hashCode());\n    }\n\n    @Test\n    void testEquals() {\n        final KeyValueImpl kv1 = new KeyValueImpl(KV.newBuilder()\n                .setKey(\"a\")\n                .setValue(ByteString.copyFromUtf8(\"valueA\"))\n                .build());\n\n        final KeyValueImpl kv2 = new KeyValueImpl(KV.newBuilder()\n                .setKey(\"a\")\n                .setValue(ByteString.copyFromUtf8(\"valueB\"))\n                .build());\n\n        final KeyValueImpl kv3 = new KeyValueImpl(KV.newBuilder()\n                .setKey(\"b\")\n                .setValue(ByteString.copyFromUtf8(\"valueA\"))\n                .build());\n\n        final KeyValueImpl kv4 = new KeyValueImpl(KV.newBuilder()\n                .setKey(\"a\")\n                .setValue(ByteString.copyFromUtf8(\"valueA\"))\n                .build());\n\n        assertThat(kv1).isNotEqualTo(kv2);\n        assertThat(kv1).isNotEqualTo(kv3);\n        assertThat(kv1).isEqualTo(kv4);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/impl/QueryResultsIteratorWithMetadataImplTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.impl;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\n\nimport com.google.protobuf.ByteString;\nimport java.util.function.Function;\nimport org.hyperledger.fabric.protos.peer.QueryResponse;\nimport org.hyperledger.fabric.protos.peer.QueryResponseMetadata;\nimport org.hyperledger.fabric.protos.peer.QueryResultBytes;\nimport org.junit.jupiter.api.Test;\n\nfinal class QueryResultsIteratorWithMetadataImplTest {\n    private static final Function<QueryResultBytes, Integer> QUERY_RESULT_BYTES_TO_KV = queryResultBytes -> 0;\n\n    @Test\n    void getMetadata() {\n        final QueryResultsIteratorWithMetadataImpl<Integer> testIter = new QueryResultsIteratorWithMetadataImpl<>(\n                null, \"\", \"\", prepareQueryResponse().toByteString(), QUERY_RESULT_BYTES_TO_KV);\n        assertThat(testIter.getMetadata().getBookmark()).isEqualTo(\"asdf\");\n        assertThat(testIter.getMetadata().getFetchedRecordsCount()).isEqualTo(2);\n    }\n\n    @Test\n    void getInvalidMetadata() {\n        assertThatThrownBy(() -> new QueryResultsIteratorWithMetadataImpl<>(\n                        null, \"\", \"\", prepareQueryResponseWrongMeta().toByteString(), QUERY_RESULT_BYTES_TO_KV))\n                .isInstanceOf(RuntimeException.class);\n    }\n\n    private QueryResponse prepareQueryResponse() {\n        final QueryResponseMetadata qrm = QueryResponseMetadata.newBuilder()\n                .setBookmark(\"asdf\")\n                .setFetchedRecordsCount(2)\n                .build();\n\n        return QueryResponse.newBuilder()\n                .setHasMore(false)\n                .setMetadata(qrm.toByteString())\n                .build();\n    }\n\n    private QueryResponse prepareQueryResponseWrongMeta() {\n        final ByteString bs = ByteString.copyFrom(new byte[] {0, 0});\n\n        return QueryResponse.newBuilder().setHasMore(false).setMetadata(bs).build();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/ledger/CompositeKeyTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.ledger;\n\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.contains;\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.hamcrest.Matchers.hasSize;\nimport static org.hamcrest.Matchers.is;\n\nimport java.util.Arrays;\nimport org.junit.jupiter.api.Test;\n\nfinal class CompositeKeyTest {\n    @Test\n    void testValidateSimpleKeys() {\n        CompositeKey.validateSimpleKeys(\"abc\", \"def\", \"ghi\");\n    }\n\n    @Test\n    void testValidateSimpleKeysException() {\n        assertThatThrownBy(() -> CompositeKey.validateSimpleKeys(\"\\u0000abc\"))\n                .isInstanceOf(CompositeKeyFormatException.class);\n    }\n\n    @Test\n    void testCompositeKeyStringStringArray() {\n        final CompositeKey key = new CompositeKey(\"abc\", \"def\", \"ghi\", \"jkl\", \"mno\");\n        assertThat(key.getObjectType(), is(equalTo(\"abc\")));\n        assertThat(key.getAttributes(), hasSize(4));\n        assertThat(key.toString(), is(equalTo(\"\\u0000abc\\u0000def\\u0000ghi\\u0000jkl\\u0000mno\\u0000\")));\n    }\n\n    @Test\n    void testCompositeKeyStringListOfString() {\n        final CompositeKey key = new CompositeKey(\"abc\", Arrays.asList(\"def\", \"ghi\", \"jkl\", \"mno\"));\n        assertThat(key.getObjectType(), is(equalTo(\"abc\")));\n        assertThat(key.getAttributes(), hasSize(4));\n        assertThat(key.toString(), is(equalTo(\"\\u0000abc\\u0000def\\u0000ghi\\u0000jkl\\u0000mno\\u0000\")));\n    }\n\n    @Test\n    void testEmptyAttributes() {\n        final CompositeKey key = new CompositeKey(\"abc\");\n        assertThat(key.getObjectType(), is(equalTo(\"abc\")));\n        assertThat(key.getAttributes(), hasSize(0));\n        assertThat(key.toString(), is(equalTo(\"\\u0000abc\\u0000\")));\n    }\n\n    @Test\n    void testCompositeKeyWithInvalidObjectTypeDelimiter() {\n        assertThatThrownBy(() -> new CompositeKey(\"ab\\u0000c\", Arrays.asList(\"def\", \"ghi\", \"jkl\", \"mno\")))\n                .isInstanceOf(CompositeKeyFormatException.class);\n    }\n\n    @Test\n    void testCompositeKeyWithInvalidAttributeDelimiter() {\n        assertThatThrownBy(() -> new CompositeKey(\"abc\", Arrays.asList(\"def\", \"ghi\", \"j\\u0000kl\", \"mno\")))\n                .isInstanceOf(CompositeKeyFormatException.class);\n    }\n\n    @Test\n    void testCompositeKeyWithInvalidObjectTypeMaxCodePoint() {\n        assertThatThrownBy(() -> new CompositeKey(\"ab\\udbff\\udfffc\", Arrays.asList(\"def\", \"ghi\", \"jkl\", \"mno\")))\n                .isInstanceOf(CompositeKeyFormatException.class);\n    }\n\n    @Test\n    void testCompositeKeyWithInvalidAttributeMaxCodePoint() {\n        assertThatThrownBy(() -> new CompositeKey(\"abc\", Arrays.asList(\"def\", \"ghi\", \"jk\\udbff\\udfffl\", \"mno\")))\n                .isInstanceOf(CompositeKeyFormatException.class);\n    }\n\n    @Test\n    void testGetObjectType() {\n        final CompositeKey key = new CompositeKey(\"abc\", Arrays.asList(\"def\", \"ghi\", \"jkl\", \"mno\"));\n        assertThat(key.getObjectType(), is(equalTo(\"abc\")));\n    }\n\n    @Test\n    void testGetAttributes() {\n        final CompositeKey key = new CompositeKey(\"abc\", Arrays.asList(\"def\", \"ghi\", \"jkl\", \"mno\"));\n        assertThat(key.getObjectType(), is(equalTo(\"abc\")));\n        assertThat(key.getAttributes(), hasSize(4));\n        assertThat(key.getAttributes(), contains(\"def\", \"ghi\", \"jkl\", \"mno\"));\n    }\n\n    @Test\n    void testToString() {\n        final CompositeKey key = new CompositeKey(\"abc\", Arrays.asList(\"def\", \"ghi\", \"jkl\", \"mno\"));\n        assertThat(key.toString(), is(equalTo(\"\\u0000abc\\u0000def\\u0000ghi\\u0000jkl\\u0000mno\\u0000\")));\n    }\n\n    @Test\n    void testParseCompositeKey() {\n        final CompositeKey key = CompositeKey.parseCompositeKey(\"\\u0000abc\\u0000def\\u0000ghi\\u0000jkl\\u0000mno\\u0000\");\n        assertThat(key.getObjectType(), is(equalTo(\"abc\")));\n        assertThat(key.getAttributes(), hasSize(4));\n        assertThat(key.getAttributes(), contains(\"def\", \"ghi\", \"jkl\", \"mno\"));\n        assertThat(key.toString(), is(equalTo(\"\\u0000abc\\u0000def\\u0000ghi\\u0000jkl\\u0000mno\\u0000\")));\n    }\n\n    @Test\n    void testParseCompositeKeyInvalidObjectType() {\n        assertThatThrownBy(() ->\n                        CompositeKey.parseCompositeKey(\"ab\\udbff\\udfffc\\u0000def\\u0000ghi\\u0000jkl\\u0000mno\\u0000\"))\n                .isInstanceOf(CompositeKeyFormatException.class);\n    }\n\n    @Test\n    void testParseCompositeKeyInvalidAttribute() {\n        assertThatThrownBy(() ->\n                        CompositeKey.parseCompositeKey(\"abc\\u0000def\\u0000ghi\\u0000jk\\udbff\\udfffl\\u0000mno\\u0000\"))\n                .isInstanceOf(CompositeKeyFormatException.class);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/ChaincodeMockPeer.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport static org.hyperledger.fabric.protos.peer.ChaincodeMessage.Type.PUT_STATE;\n\nimport io.grpc.Server;\nimport io.grpc.ServerBuilder;\nimport io.grpc.stub.StreamObserver;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.logging.Logger;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.ChaincodeSupportGrpc;\nimport org.hyperledger.fabric.shim.utils.TimeoutUtil;\n\n/** Mock peer implementation */\npublic final class ChaincodeMockPeer {\n    private static final Logger LOGGER = Logger.getLogger(ChaincodeMockPeer.class.getName());\n\n    private final int port;\n    private final Server server;\n    private final ChaincodeMockPeerService service;\n\n    /**\n     * Constructor\n     *\n     * @param scenario list of scenario steps\n     * @param port mock peer communication port\n     * @throws IOException\n     */\n    public ChaincodeMockPeer(final List<ScenarioStep> scenario, final int port) {\n        this.port = port;\n        this.service = new ChaincodeMockPeerService(scenario);\n        final ServerBuilder<?> sb = ServerBuilder.forPort(port);\n        this.server = sb.addService(this.service).build();\n    }\n\n    /** Start serving requests. */\n    @SuppressWarnings(\"PMD.SystemPrintln\")\n    public void start() throws IOException {\n        server.start();\n        LOGGER.info(() -> \"Server started, listening on \" + port);\n        Runtime.getRuntime().addShutdownHook(new Thread() {\n            @Override\n            public void run() {\n                // Use stderr here since the logger may have been reset by its JVM shutdown hook.\n                System.err.println(\"*** shutting down gRPC server since JVM is shutting down\");\n                ChaincodeMockPeer.this.stop();\n                System.err.println(\"*** server shut down\");\n            }\n        });\n    }\n\n    /** Stop serving requests and shutdown resources. */\n    public void stop() {\n        if (server != null) {\n            server.shutdownNow();\n            try {\n                server.awaitTermination();\n            } catch (final InterruptedException ignored) {\n            }\n        }\n    }\n\n    /**\n     * Send message from mock peer to chaincode (to start init, invoke, etc)\n     *\n     * @param msg\n     */\n    public void send(final ChaincodeMessage msg) {\n        this.service.lastMessageSend = msg;\n\n        LOGGER.info(() -> \"Mock peer => Sending message: \" + msg);\n        this.service.send(msg);\n    }\n\n    /**\n     * Check last executed step number, to check where in scenario we stopped\n     *\n     * @return\n     */\n    public int getLastExecutedStep() {\n        return this.service.lastExecutedStepNumber;\n    }\n\n    /** @return last received message from chaincode */\n    public ChaincodeMessage getLastMessageRcvd() {\n        return this.service.lastMessageRcvd;\n    }\n\n    public List<ChaincodeMessage> getAllReceivedMessages() {\n        return this.service.allMessages;\n    }\n\n    /** @return last message sent by peer to chaincode */\n    public ChaincodeMessage getLastMessageSend() {\n        return this.service.lastMessageSend;\n    }\n\n    /**\n     * Creates new instance of mock peer server, starts it and returns\n     *\n     * @param scenario\n     * @return\n     * @throws Exception\n     */\n    public static ChaincodeMockPeer startServer(final List<ScenarioStep> scenario) throws Exception {\n        final ChaincodeMockPeer server = new ChaincodeMockPeer(scenario, 7052);\n        server.start();\n        return server;\n    }\n\n    private static class ChaincodeMockPeerService extends ChaincodeSupportGrpc.ChaincodeSupportImplBase {\n        private final List<ScenarioStep> scenario;\n        private int lastExecutedStepNumber;\n        private ChaincodeMessage lastMessageRcvd;\n        private ChaincodeMessage lastMessageSend;\n        private final List<ChaincodeMessage> allMessages = new ArrayList<>();\n        private StreamObserver<ChaincodeMessage> observer;\n\n        // create a lock, with fair property\n        private final ReentrantLock lock = new ReentrantLock(true);\n\n        ChaincodeMockPeerService(final List<ScenarioStep> scenario) {\n            this.scenario = scenario;\n            this.lastExecutedStepNumber = 0;\n        }\n\n        public void send(final ChaincodeMessage msg) {\n            lock.lock();\n\n            observer.onNext(msg);\n            lock.unlock();\n        }\n\n        /**\n         * Attaching observer to steams\n         *\n         * @param responseObserver\n         * @return\n         */\n        @Override\n        public StreamObserver<ChaincodeMessage> register(final StreamObserver<ChaincodeMessage> responseObserver) {\n            observer = responseObserver;\n            return new StreamObserver<>() {\n\n                /**\n                 * Handling incoming messages\n                 *\n                 * @param chaincodeMessage\n                 */\n                @Override\n                @SuppressWarnings(\"PMD.AvoidCatchingThrowable\")\n                public void onNext(final ChaincodeMessage chaincodeMessage) {\n                    try {\n                        LOGGER.info(() -> \"Mock peer => Got message: \" + chaincodeMessage);\n                        ChaincodeMockPeerService.this.lastMessageRcvd = chaincodeMessage;\n                        ChaincodeMockPeerService.this.allMessages.add(chaincodeMessage);\n                        if (chaincodeMessage.getType().equals(PUT_STATE)) {\n                            final ChaincodeMessage m = ChaincodeMessage.newBuilder()\n                                    .setType(ChaincodeMessage.Type.RESPONSE)\n                                    .setChannelId(chaincodeMessage.getChannelId())\n                                    .setTxid(chaincodeMessage.getTxid())\n                                    .build();\n                            Thread.sleep(500);\n                            ChaincodeMockPeerService.this.send(m);\n                        } else if (ChaincodeMockPeerService.this.scenario.size() > 0) {\n                            final ScenarioStep step = ChaincodeMockPeerService.this.scenario.get(0);\n                            ChaincodeMockPeerService.this.scenario.remove(0);\n                            if (step.expected(chaincodeMessage)) {\n                                final List<ChaincodeMessage> nextSteps = step.next();\n                                for (final ChaincodeMessage m : nextSteps) {\n                                    ChaincodeMockPeerService.this.lastMessageSend = m;\n                                    LOGGER.info(() -> \"Mock peer => Sending response message: \" + m);\n                                    ChaincodeMockPeerService.this.send(m);\n                                }\n                            } else {\n                                LOGGER.warning(() -> \"Non expected message rcvd in step \"\n                                        + step.getClass().getSimpleName());\n                            }\n                            ChaincodeMockPeerService.this.lastExecutedStepNumber++;\n                        }\n                    } catch (final Throwable t) {\n                        t.printStackTrace();\n                    }\n                }\n\n                @Override\n                public void onError(final Throwable throwable) {\n                    throwable.printStackTrace();\n                }\n\n                @Override\n                public void onCompleted() {}\n            };\n        }\n    }\n\n    @SuppressWarnings(\"PMD.SystemPrintln\")\n    public static void checkScenarioStepEnded(\n            final ChaincodeMockPeer s, final int step, final int timeout, final TimeUnit units) throws Exception {\n        try {\n            TimeoutUtil.runWithTimeout(\n                    new Thread(() -> {\n                        while (true) {\n                            if (s.getLastExecutedStep() == step) {\n                                return;\n                            }\n                            try {\n                                Thread.sleep(500);\n                            } catch (final InterruptedException ignored) {\n                            }\n                        }\n                    }),\n                    timeout,\n                    units);\n        } catch (final TimeoutException e) {\n            System.out.println(\"Got timeout, step \" + step + \" not finished\");\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/CompleteStep.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport java.util.Collections;\nimport java.util.List;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\n\n/** Waits for COMPLETED message, sends nothing back */\npublic final class CompleteStep implements ScenarioStep {\n    @Override\n    public boolean expected(final ChaincodeMessage msg) {\n        return msg.getType() == ChaincodeMessage.Type.COMPLETED;\n    }\n\n    @Override\n    public List<ChaincodeMessage> next() {\n        return Collections.emptyList();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/DelValueStep.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\n\n/**\n * Simulates delState() invocation in chaincode Waits for DEL_STATE message from chaincode and sends back response with\n * empty payload\n */\npublic final class DelValueStep implements ScenarioStep {\n    private ChaincodeMessage orgMsg;\n\n    @Override\n    public boolean expected(final ChaincodeMessage msg) {\n        orgMsg = msg;\n        return msg.getType() == ChaincodeMessage.Type.DEL_STATE;\n    }\n\n    @Override\n    public List<ChaincodeMessage> next() {\n        final List<ChaincodeMessage> list = new ArrayList<>();\n        list.add(ChaincodeMessage.newBuilder()\n                .setType(ChaincodeMessage.Type.RESPONSE)\n                .setChannelId(orgMsg.getChannelId())\n                .setTxid(orgMsg.getTxid())\n                .build());\n        return list;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/ErrorResponseStep.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport java.util.Collections;\nimport java.util.List;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\n\n/** Error message from chaincode side, no response sent */\npublic final class ErrorResponseStep implements ScenarioStep {\n    @Override\n    public boolean expected(final ChaincodeMessage msg) {\n        return msg.getType() == ChaincodeMessage.Type.ERROR;\n    }\n\n    @Override\n    public List<ChaincodeMessage> next() {\n        return Collections.emptyList();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/GetHistoryForKeyStep.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport static java.util.stream.Collectors.toList;\n\nimport com.google.protobuf.ByteString;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport org.hyperledger.fabric.protos.ledger.queryresult.KeyModification;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.QueryResponse;\nimport org.hyperledger.fabric.protos.peer.QueryResultBytes;\n\npublic final class GetHistoryForKeyStep implements ScenarioStep {\n    private ChaincodeMessage orgMsg;\n    private final String[] values;\n    private final boolean hasNext;\n\n    /**\n     * Initiate step\n     *\n     * @param hasNext is response message QueryResponse hasMore field set\n     * @param vals list of keys to generate (\"key\" => \"key Value\") pairs\n     */\n    public GetHistoryForKeyStep(final boolean hasNext, final String... vals) {\n        this.values = Arrays.copyOf(vals, vals.length);\n        this.hasNext = hasNext;\n    }\n\n    @Override\n    public boolean expected(final ChaincodeMessage msg) {\n        orgMsg = msg;\n        return msg.getType() == ChaincodeMessage.Type.GET_HISTORY_FOR_KEY;\n    }\n\n    @Override\n    public List<ChaincodeMessage> next() {\n        final List<KeyModification> keyModifications = Arrays.asList(values).stream()\n                .map(x -> KeyModification.newBuilder()\n                        .setTxId(x)\n                        .setValue(ByteString.copyFromUtf8(x + \" Value\"))\n                        .build())\n                .collect(toList());\n\n        final QueryResponse.Builder builder = QueryResponse.newBuilder();\n        builder.setHasMore(hasNext);\n        keyModifications.stream()\n                .forEach(kv -> builder.addResults(QueryResultBytes.newBuilder().setResultBytes(kv.toByteString())));\n        final ByteString historyPayload = builder.build().toByteString();\n\n        final List<ChaincodeMessage> list = new ArrayList<>();\n        list.add(ChaincodeMessage.newBuilder()\n                .setType(ChaincodeMessage.Type.RESPONSE)\n                .setChannelId(orgMsg.getChannelId())\n                .setTxid(orgMsg.getTxid())\n                .setPayload(historyPayload)\n                .build());\n        return list;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/GetQueryResultStep.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\n\n/**\n * Simulates query invocation. Waits for GET_QUERY_RESULT Returns message that contains list of results in form (\"key\"\n * => \"key Value\")*\n */\npublic final class GetQueryResultStep extends QueryResultStep {\n\n    /**\n     * Initiate step\n     *\n     * @param hasNext is response message QueryResponse hasMore field set\n     * @param vals list of keys to generate (\"key\" => \"key Value\") pairs\n     */\n    public GetQueryResultStep(final boolean hasNext, final String... vals) {\n        super(hasNext, vals);\n    }\n\n    @Override\n    public boolean expected(final ChaincodeMessage msg) {\n        super.orgMsg = msg;\n        return msg.getType() == ChaincodeMessage.Type.GET_QUERY_RESULT;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/GetStateByRangeStep.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\n\n/**\n * Simulates getStateByRange Waits for GET_STATE_BY_RANGE message Returns message that contains list of results in form\n * (\"key\" => \"key Value\")*\n */\npublic final class GetStateByRangeStep extends QueryResultStep {\n\n    /**\n     * Initiate step\n     *\n     * @param hasNext is response message QueryResponse hasMore field set\n     * @param vals list of keys to generate (\"key\" => \"key Value\") pairs\n     */\n    public GetStateByRangeStep(final boolean hasNext, final String... vals) {\n        super(hasNext, vals);\n    }\n\n    @Override\n    public boolean expected(final ChaincodeMessage msg) {\n        super.orgMsg = msg;\n        return msg.getType() == ChaincodeMessage.Type.GET_STATE_BY_RANGE;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/GetStateMetadata.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport com.google.protobuf.ByteString;\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.MetaDataKeys;\nimport org.hyperledger.fabric.protos.peer.StateMetadata;\nimport org.hyperledger.fabric.protos.peer.StateMetadataResult;\nimport org.hyperledger.fabric.shim.ext.sbe.StateBasedEndorsement;\n\n/**\n * simulates Handler.getStateMetadata Waits for GET_STATE_METADATA message Returns response message with stored metadata\n */\npublic final class GetStateMetadata implements ScenarioStep {\n    private ChaincodeMessage orgMsg;\n    private final byte[] val;\n\n    /** @param sbe StateBasedEndorsement to return as one and only one metadata entry */\n    public GetStateMetadata(final StateBasedEndorsement sbe) {\n        val = sbe.policy();\n    }\n\n    @Override\n    public boolean expected(final ChaincodeMessage msg) {\n        orgMsg = msg;\n        return msg.getType() == ChaincodeMessage.Type.GET_STATE_METADATA;\n    }\n\n    @Override\n    public List<ChaincodeMessage> next() {\n        final List<StateMetadata> entriesList = new ArrayList<>();\n        final StateMetadata validationValue = StateMetadata.newBuilder()\n                .setMetakey(MetaDataKeys.VALIDATION_PARAMETER.toString())\n                .setValue(ByteString.copyFrom(val))\n                .build();\n        entriesList.add(validationValue);\n        final StateMetadataResult stateMetadataResult =\n                StateMetadataResult.newBuilder().addAllEntries(entriesList).build();\n        final List<ChaincodeMessage> list = new ArrayList<>();\n        list.add(ChaincodeMessage.newBuilder()\n                .setType(ChaincodeMessage.Type.RESPONSE)\n                .setChannelId(orgMsg.getChannelId())\n                .setTxid(orgMsg.getTxid())\n                .setPayload(stateMetadataResult.toByteString())\n                .build());\n        return list;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/GetValueStep.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport com.google.protobuf.ByteString;\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\n\n/** Simulates getState Waits for GET_STATE message Returns response message with value as payload */\npublic final class GetValueStep implements ScenarioStep {\n    private ChaincodeMessage orgMsg;\n    private final String val;\n\n    /** @param val value to return */\n    public GetValueStep(final String val) {\n        this.val = val;\n    }\n\n    @Override\n    public boolean expected(final ChaincodeMessage msg) {\n        orgMsg = msg;\n        return msg.getType() == ChaincodeMessage.Type.GET_STATE;\n    }\n\n    @Override\n    public List<ChaincodeMessage> next() {\n        final ByteString getPayload = ByteString.copyFromUtf8(val);\n        final List<ChaincodeMessage> list = new ArrayList<>();\n        list.add(ChaincodeMessage.newBuilder()\n                .setType(ChaincodeMessage.Type.RESPONSE)\n                .setChannelId(orgMsg.getChannelId())\n                .setTxid(orgMsg.getTxid())\n                .setPayload(getPayload)\n                .build());\n        return list;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/InvokeChaincodeStep.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport com.google.protobuf.ByteString;\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.Response;\nimport org.hyperledger.fabric.shim.Chaincode;\n\n/**\n * Simulates another chaincode invocation Waits for INVOKE_CHAINCODE Sends back RESPONSE message with chaincode response\n * inside\n */\npublic final class InvokeChaincodeStep implements ScenarioStep {\n    private ChaincodeMessage orgMsg;\n\n    @Override\n    public boolean expected(final ChaincodeMessage msg) {\n        orgMsg = msg;\n        return msg.getType() == ChaincodeMessage.Type.INVOKE_CHAINCODE;\n    }\n\n    /**\n     * @return Chaincode response packed as payload inside COMPLETE message packed as payload inside RESPONSE message\n     */\n    @Override\n    public List<ChaincodeMessage> next() {\n        final ByteString chaincodeResponse = Response.newBuilder()\n                .setStatus(Chaincode.Response.Status.SUCCESS.getCode())\n                .setMessage(\"OK\")\n                .build()\n                .toByteString();\n        final ByteString completePayload = ChaincodeMessage.newBuilder()\n                .setType(ChaincodeMessage.Type.COMPLETED)\n                .setChannelId(orgMsg.getChannelId())\n                .setTxid(orgMsg.getTxid())\n                .setPayload(chaincodeResponse)\n                .build()\n                .toByteString();\n        final List<ChaincodeMessage> list = new ArrayList<>();\n        list.add(ChaincodeMessage.newBuilder()\n                .setType(ChaincodeMessage.Type.RESPONSE)\n                .setChannelId(orgMsg.getChannelId())\n                .setTxid(orgMsg.getTxid())\n                .setPayload(completePayload)\n                .build());\n        return list;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/PurgeValueStep.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\n\n/**\n * Simulates purgePrivateData() invocation in chaincode Waits for PURGE_PRIVATE_DATA message from chaincode and sends\n * back response with empty payload\n */\npublic final class PurgeValueStep implements ScenarioStep {\n\n    private ChaincodeMessage orgMsg;\n\n    @Override\n    public boolean expected(final ChaincodeMessage msg) {\n        orgMsg = msg;\n        return msg.getType() == ChaincodeMessage.Type.PURGE_PRIVATE_DATA;\n    }\n\n    @Override\n    public List<ChaincodeMessage> next() {\n        final List<ChaincodeMessage> list = new ArrayList<>();\n        list.add(ChaincodeMessage.newBuilder()\n                .setType(ChaincodeMessage.Type.RESPONSE)\n                .setChannelId(orgMsg.getChannelId())\n                .setTxid(orgMsg.getTxid())\n                .build());\n        return list;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/PutStateMetadata.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport com.google.protobuf.InvalidProtocolBufferException;\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.MetaDataKeys;\nimport org.hyperledger.fabric.shim.ext.sbe.StateBasedEndorsement;\nimport org.hyperledger.fabric.shim.ext.sbe.impl.StateBasedEndorsementFactory;\n\n/**\n * * Simulates Handler.putStateMetadata() invocation from chaincode side * Waits for PUT_STATE_METADATA message from\n * chaincode, including metadata entry with validation metadata and sends back response with empty payload\n */\npublic final class PutStateMetadata implements ScenarioStep {\n    private ChaincodeMessage orgMsg;\n    private final StateBasedEndorsement val;\n\n    public PutStateMetadata(final StateBasedEndorsement sbe) {\n        val = sbe;\n    }\n\n    /**\n     * Check incoming message If message type is PUT_STATE_METADATA and payload match to passed in constructor\n     *\n     * @param msg message from chaincode\n     * @return\n     */\n    @Override\n    public boolean expected(final ChaincodeMessage msg) {\n        orgMsg = msg;\n        org.hyperledger.fabric.protos.peer.PutStateMetadata psm;\n        try {\n            psm = org.hyperledger.fabric.protos.peer.PutStateMetadata.parseFrom(msg.getPayload());\n        } catch (final InvalidProtocolBufferException e) {\n            return false;\n        }\n        final StateBasedEndorsement msgSbe = StateBasedEndorsementFactory.getInstance()\n                .newStateBasedEndorsement(psm.getMetadata().getValue().toByteArray());\n        return msg.getType() == ChaincodeMessage.Type.PUT_STATE_METADATA\n                && MetaDataKeys.VALIDATION_PARAMETER\n                        .toString()\n                        .equals(psm.getMetadata().getMetakey())\n                && (msgSbe.listOrgs().size() == val.listOrgs().size());\n    }\n\n    @Override\n    public List<ChaincodeMessage> next() {\n        final List<ChaincodeMessage> list = new ArrayList<>();\n        list.add(ChaincodeMessage.newBuilder()\n                .setType(ChaincodeMessage.Type.RESPONSE)\n                .setChannelId(orgMsg.getChannelId())\n                .setTxid(orgMsg.getTxid())\n                .build());\n        return list;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/PutValueStep.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport com.google.protobuf.InvalidProtocolBufferException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.PutState;\n\n/**\n * Simulates putState() invocation in chaincode Waits for PUT_STATE message from chaincode, including value and sends\n * back response with empty payload\n */\npublic final class PutValueStep implements ScenarioStep {\n    private ChaincodeMessage orgMsg;\n    private final String val;\n\n    /**\n     * Initiate step\n     *\n     * @param val\n     */\n    public PutValueStep(final String val) {\n        this.val = val;\n    }\n\n    /**\n     * Check incoming message If message type is PUT_STATE and payload equal to passed in constructor\n     *\n     * @param msg message from chaincode\n     * @return\n     */\n    @Override\n    public boolean expected(final ChaincodeMessage msg) {\n        orgMsg = msg;\n        PutState putMsg = null;\n        try {\n            putMsg = PutState.parseFrom(msg.getPayload());\n        } catch (final InvalidProtocolBufferException e) {\n            return false;\n        }\n        return val.equals(new String(putMsg.getValue().toByteArray(), StandardCharsets.UTF_8))\n                && msg.getType() == ChaincodeMessage.Type.PUT_STATE;\n    }\n\n    @Override\n    public List<ChaincodeMessage> next() {\n        final List<ChaincodeMessage> list = new ArrayList<>();\n        list.add(ChaincodeMessage.newBuilder()\n                .setType(ChaincodeMessage.Type.RESPONSE)\n                .setChannelId(orgMsg.getChannelId())\n                .setTxid(orgMsg.getTxid())\n                .build());\n        return list;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/QueryCloseStep.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\n\n/**\n * Simulate last query (close) step. Happens after passing over all query result Waits for QUERY_STATE_CLOSE Sends back\n * response with empty payload\n */\npublic final class QueryCloseStep implements ScenarioStep {\n    private ChaincodeMessage orgMsg;\n\n    @Override\n    public boolean expected(final ChaincodeMessage msg) {\n        orgMsg = msg;\n        return msg.getType() == ChaincodeMessage.Type.QUERY_STATE_CLOSE;\n    }\n\n    /** @return RESPONSE message with empty payload */\n    @Override\n    public List<ChaincodeMessage> next() {\n        final List<ChaincodeMessage> list = new ArrayList<>();\n        list.add(ChaincodeMessage.newBuilder()\n                .setType(ChaincodeMessage.Type.RESPONSE)\n                .setChannelId(orgMsg.getChannelId())\n                .setTxid(orgMsg.getTxid())\n                .build());\n        return list;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/QueryNextStep.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\n\n/**\n * Simulates requesting/receiving next set of results for query Waits for QUERY_STATE_NEXT Returns message that contains\n * list of results in form (\"key\" => \"key Value\")*\n */\npublic final class QueryNextStep extends QueryResultStep {\n\n    /**\n     * Initiate step\n     *\n     * @param hasNext is response message QueryResponse hasMore field set\n     * @param vals list of keys to generate (\"key\" => \"key Value\") pairs\n     */\n    public QueryNextStep(final boolean hasNext, final String... vals) {\n        super(hasNext, vals);\n    }\n\n    @Override\n    public boolean expected(final ChaincodeMessage msg) {\n        super.orgMsg = msg;\n        return msg.getType() == ChaincodeMessage.Type.QUERY_STATE_NEXT;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/QueryResultStep.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport static java.util.stream.Collectors.toList;\n\nimport com.google.protobuf.ByteString;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport org.hyperledger.fabric.protos.ledger.queryresult.KV;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.QueryResponse;\nimport org.hyperledger.fabric.protos.peer.QueryResultBytes;\n\n/** Base class for multi result query steps/messages */\npublic abstract class QueryResultStep implements ScenarioStep {\n    protected ChaincodeMessage orgMsg;\n    protected final String[] values;\n    protected final boolean hasNext;\n\n    /**\n     * Initiate step\n     *\n     * @param hasNext is response message QueryResponse hasMore field set\n     * @param vals list of keys to generate (\"key\" => \"key Value\") pairs\n     */\n    QueryResultStep(final boolean hasNext, final String... vals) {\n        this.values = Arrays.copyOf(vals, vals.length);\n        this.hasNext = hasNext;\n    }\n\n    /**\n     * Generate response message that list of (key => value) pairs\n     *\n     * @return\n     */\n    @Override\n    public List<ChaincodeMessage> next() {\n        final List<KV> keyValues = Arrays.asList(values).stream()\n                .map(x -> KV.newBuilder()\n                        .setKey(x)\n                        .setValue(ByteString.copyFromUtf8(x + \" Value\"))\n                        .build())\n                .collect(toList());\n\n        final QueryResponse.Builder builder = QueryResponse.newBuilder();\n        builder.setHasMore(hasNext);\n        keyValues.stream()\n                .forEach(kv -> builder.addResults(QueryResultBytes.newBuilder().setResultBytes(kv.toByteString())));\n        final ByteString rangePayload = builder.build().toByteString();\n\n        final List<ChaincodeMessage> list = new ArrayList<>();\n        list.add(ChaincodeMessage.newBuilder()\n                .setType(ChaincodeMessage.Type.RESPONSE)\n                .setChannelId(orgMsg.getChannelId())\n                .setTxid(orgMsg.getTxid())\n                .setPayload(rangePayload)\n                .build());\n        return list;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/RegisterStep.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\n\n/**\n * Simulates chaincode registration after start Waits for REGISTER message from chaincode Sends back pair of messages:\n * REGISTERED and READY\n */\npublic final class RegisterStep implements ScenarioStep {\n\n    private ChaincodeMessage orgMsg;\n\n    @Override\n    public boolean expected(final ChaincodeMessage msg) {\n        orgMsg = msg;\n        return msg.getType() == ChaincodeMessage.Type.REGISTER;\n    }\n\n    @Override\n    public List<ChaincodeMessage> next() {\n        final List<ChaincodeMessage> list = new ArrayList<>();\n        list.add(ChaincodeMessage.newBuilder()\n                .setType(ChaincodeMessage.Type.REGISTERED)\n                .build());\n        list.add(ChaincodeMessage.newBuilder()\n                .setType(ChaincodeMessage.Type.READY)\n                .build());\n        return list;\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/mock/peer/ScenarioStep.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.mock.peer;\n\nimport java.util.List;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\n\npublic interface ScenarioStep {\n    /**\n     * Validate incoming message from chaincode side\n     *\n     * @param msg message from chaincode\n     * @return is incoming message was expected\n     */\n    boolean expected(ChaincodeMessage msg);\n\n    /**\n     * List of messages send from peer to chaincode as response(s)\n     *\n     * @return\n     */\n    List<ChaincodeMessage> next();\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/utils/MessageUtil.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage org.hyperledger.fabric.shim.utils;\n\nimport com.google.protobuf.ByteString;\nimport org.hyperledger.fabric.protos.peer.ChaincodeEvent;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\n\npublic final class MessageUtil {\n\n    private MessageUtil() {}\n\n    /**\n     * Generate chaincode messages\n     *\n     * @param type\n     * @param channelId\n     * @param txId\n     * @param payload\n     * @param event\n     * @return\n     */\n    public static ChaincodeMessage newEventMessage(\n            final ChaincodeMessage.Type type,\n            final String channelId,\n            final String txId,\n            final ByteString payload,\n            final ChaincodeEvent event) {\n        final ChaincodeMessage.Builder builder = ChaincodeMessage.newBuilder()\n                .setType(type)\n                .setChannelId(channelId)\n                .setTxid(txId)\n                .setPayload(payload);\n        if (event != null) {\n            builder.setChaincodeEvent(event);\n        }\n        return builder.build();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/shim/utils/TimeoutUtil.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.shim.utils;\n\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\n\n/** Give possibility to stop runnable execution after specific time, if not ended */\npublic final class TimeoutUtil {\n\n    private TimeoutUtil() {}\n\n    public static void runWithTimeout(final Runnable callable, final long timeout, final TimeUnit timeUnit)\n            throws Exception {\n        final ExecutorService executor = Executors.newSingleThreadExecutor();\n        final CountDownLatch latch = new CountDownLatch(1);\n        final Thread t = new Thread(() -> {\n            try {\n                callable.run();\n            } finally {\n                latch.countDown();\n            }\n        });\n        try {\n            executor.execute(t);\n            if (!latch.await(timeout, timeUnit)) {\n                throw new TimeoutException();\n            }\n        } finally {\n            executor.shutdown();\n            t.interrupt();\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/traces/TracesTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.traces;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport io.opentelemetry.api.trace.Span;\nimport java.util.Properties;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.hyperledger.fabric.traces.impl.DefaultTracesProvider;\nimport org.hyperledger.fabric.traces.impl.NullProvider;\nimport org.hyperledger.fabric.traces.impl.OpenTelemetryTracesProvider;\nimport org.junit.jupiter.api.DisplayName;\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\n\nfinal class TracesTest {\n\n    private static final class TestProvider implements TracesProvider {\n\n        public TestProvider() {}\n\n        @Override\n        public void initialize(final Properties props) {}\n\n        @Override\n        public Span createSpan(final ChaincodeStub stub) {\n            return null;\n        }\n    }\n\n    @Nested\n    @DisplayName(\"Traces initialize\")\n    final class Initialize {\n\n        @Test\n        void tracesDisabled() {\n            final TracesProvider provider = Traces.initialize(new Properties());\n            assertThat(provider).isExactlyInstanceOf(NullProvider.class);\n        }\n\n        @Test\n        void tracesEnabledUnknownProvider() {\n            final Properties props = new Properties();\n            props.put(\"CHAINCODE_TRACES_PROVIDER\", \"org.example.traces.provider\");\n            props.put(\"CHAINCODE_TRACES_ENABLED\", \"true\");\n\n            assertThrows(\n                    RuntimeException.class,\n                    () -> {\n                        final TracesProvider provider = Traces.initialize(props);\n                    },\n                    \"Unable to start traces\");\n        }\n\n        @Test\n        void tracesNoProvider() {\n            final Properties props = new Properties();\n            props.put(\"CHAINCODE_TRACES_ENABLED\", \"true\");\n\n            final TracesProvider provider = Traces.initialize(props);\n            assertTrue(provider instanceof DefaultTracesProvider);\n        }\n\n        @Test\n        void tracesOpenTelemetryProvider() {\n            final Properties props = new Properties();\n            props.put(\"CHAINCODE_TRACES_PROVIDER\", \"org.hyperledger.fabric.traces.impl.OpenTelemetryTracesProvider\");\n            props.put(\"CHAINCODE_TRACES_ENABLED\", \"true\");\n\n            final TracesProvider provider = Traces.initialize(props);\n            assertTrue(provider instanceof OpenTelemetryTracesProvider);\n        }\n\n        @Test\n        void tracesValid() {\n            final Properties props = new Properties();\n            props.put(\"CHAINCODE_TRACES_PROVIDER\", TracesTest.TestProvider.class.getName());\n            props.put(\"CHAINCODE_TRACES_ENABLED\", \"true\");\n            final TracesProvider provider = Traces.initialize(props);\n\n            assertThat(provider).isExactlyInstanceOf(TracesTest.TestProvider.class);\n        }\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/traces/impl/DefaultProviderTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.traces.impl;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\nimport io.opentelemetry.api.trace.Span;\nimport org.hyperledger.fabric.contract.ChaincodeStubNaiveImpl;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.junit.jupiter.api.Test;\n\nfinal class DefaultProviderTest {\n\n    @Test\n    void testDefaultProvider() {\n        DefaultTracesProvider provider = new DefaultTracesProvider();\n        ChaincodeStub stub = new ChaincodeStubNaiveImpl();\n        Span span = provider.createSpan(stub);\n        assertThat(span).isNull();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/traces/impl/OpenTelemetryPropertiesTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.traces.impl;\n\nimport static java.time.temporal.ChronoUnit.DAYS;\nimport static java.time.temporal.ChronoUnit.HOURS;\nimport static java.time.temporal.ChronoUnit.MILLIS;\nimport static java.time.temporal.ChronoUnit.MINUTES;\nimport static java.time.temporal.ChronoUnit.SECONDS;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\n\nimport io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;\nimport java.time.Duration;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport org.junit.jupiter.api.Test;\n\nfinal class OpenTelemetryPropertiesTest {\n\n    @Test\n    void testOverrideValue() {\n        OpenTelemetryProperties props = new OpenTelemetryProperties(\n                Collections.singletonMap(\"foo\", \"bar\"), Collections.singletonMap(\"foo\", \"foobar\"));\n        assertThat(props.getString(\"foo\")).isEqualTo(\"foobar\");\n    }\n\n    @Test\n    void testCanGetDurationDays() {\n        OpenTelemetryProperties props = new OpenTelemetryProperties(Collections.singletonMap(\"foo\", \"5d\"));\n        assertThat(props.getDuration(\"foo\")).isEqualTo(Duration.of(5, DAYS));\n    }\n\n    @Test\n    void testCanGetDurationHours() {\n        OpenTelemetryProperties props = new OpenTelemetryProperties(Collections.singletonMap(\"foo\", \"5h\"));\n        assertThat(props.getDuration(\"foo\")).isEqualTo(Duration.of(5, HOURS));\n    }\n\n    @Test\n    void testCanGetDurationMinutes() {\n        OpenTelemetryProperties props = new OpenTelemetryProperties(Collections.singletonMap(\"foo\", \"5m\"));\n        assertThat(props.getDuration(\"foo\")).isEqualTo(Duration.of(5, MINUTES));\n    }\n\n    @Test\n    void testCanGetDurationSeconds() {\n        OpenTelemetryProperties props = new OpenTelemetryProperties(Collections.singletonMap(\"foo\", \"5s\"));\n        assertThat(props.getDuration(\"foo\")).isEqualTo(Duration.of(5, SECONDS));\n    }\n\n    @Test\n    void testCanGetDurationMilliSeconds() {\n        OpenTelemetryProperties props = new OpenTelemetryProperties(Collections.singletonMap(\"foo\", \"5ms\"));\n        assertThat(props.getDuration(\"foo\")).isEqualTo(Duration.of(5, MILLIS));\n    }\n\n    @Test\n    void testCanGetDurationInvalid() {\n        OpenTelemetryProperties props = new OpenTelemetryProperties(Collections.singletonMap(\"foo\", \"5foo\"));\n        assertThatThrownBy(() -> props.getDuration(\"foo\")).isInstanceOf(ConfigurationException.class);\n    }\n\n    @Test\n    void testGetDouble() {\n        OpenTelemetryProperties props = new OpenTelemetryProperties(Collections.singletonMap(\"foo\", \"5.23\"));\n        assertThat(props.getDouble(\"foo\")).isEqualTo(5.23d);\n        assertThat(props.getDouble(\"bar\")).isNull();\n    }\n\n    @Test\n    void testGetDoubleInvalid() {\n        OpenTelemetryProperties props = new OpenTelemetryProperties(Collections.singletonMap(\"foo\", \"5foo\"));\n        assertThatThrownBy(() -> props.getDouble(\"foo\")).isInstanceOf(ConfigurationException.class);\n    }\n\n    @Test\n    void testGetLong() {\n        OpenTelemetryProperties props = new OpenTelemetryProperties(Collections.singletonMap(\"foo\", \"500003\"));\n        assertThat(props.getLong(\"foo\")).isEqualTo(500003L);\n        assertThat(props.getLong(\"bar\")).isNull();\n    }\n\n    @Test\n    void testGetInt() {\n        OpenTelemetryProperties props = new OpenTelemetryProperties(Collections.singletonMap(\"foo\", \"500003\"));\n        assertThat(props.getInt(\"foo\")).isEqualTo(500003);\n        assertThat(props.getInt(\"bar\")).isNull();\n    }\n\n    @Test\n    void testGetBoolean() {\n        OpenTelemetryProperties props = new OpenTelemetryProperties(Collections.singletonMap(\"foo\", \"true\"));\n        assertThat(props.getBoolean(\"foo\")).isTrue();\n        assertThat(props.getBoolean(\"bar\")).isNull();\n    }\n\n    @Test\n    void testGetList() {\n        OpenTelemetryProperties props = new OpenTelemetryProperties(Collections.singletonMap(\"foo\", \"foo,bar,foobar\"));\n        assertThat(props.getList(\"foo\")).isEqualTo(Arrays.asList(\"foo\", \"bar\", \"foobar\"));\n        assertThat(props.getList(\"bar\")).isEqualTo(Collections.emptyList());\n    }\n\n    @Test\n    void testGetMap() {\n        OpenTelemetryProperties props =\n                new OpenTelemetryProperties(Collections.singletonMap(\"foo\", \"foo=bar,foobar=noes\"));\n        Map<String, String> expected = new HashMap<>();\n        expected.put(\"foo\", \"bar\");\n        expected.put(\"foobar\", \"noes\");\n        assertThat(props.getMap(\"foo\")).isEqualTo(expected);\n    }\n\n    @Test\n    void testGetMapInvalid() {\n        OpenTelemetryProperties props =\n                new OpenTelemetryProperties(Collections.singletonMap(\"foo\", \"foo/bar,foobar/noes\"));\n        Map<String, String> expected = new HashMap<>();\n        assertThatThrownBy(() -> props.getMap(\"foo\")).isInstanceOf(ConfigurationException.class);\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/traces/impl/OpenTelemetryTracesProviderTest.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.traces.impl;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\nimport io.grpc.ManagedChannelBuilder;\nimport io.grpc.Server;\nimport io.grpc.ServerCall;\nimport io.grpc.ServerCallHandler;\nimport io.grpc.ServerMethodDefinition;\nimport io.grpc.ServerServiceDefinition;\nimport io.grpc.Status;\nimport io.grpc.inprocess.InProcessChannelBuilder;\nimport io.grpc.inprocess.InProcessServerBuilder;\nimport io.grpc.stub.StreamObserver;\nimport io.opentelemetry.api.trace.Span;\nimport io.opentelemetry.sdk.trace.data.SpanData;\nimport java.util.List;\nimport java.util.Properties;\nimport java.util.concurrent.CompletableFuture;\nimport java.util.concurrent.TimeUnit;\nimport org.hyperledger.fabric.contract.ChaincodeStubNaiveImpl;\nimport org.hyperledger.fabric.metrics.Metrics;\nimport org.hyperledger.fabric.protos.peer.ChaincodeGrpc;\nimport org.hyperledger.fabric.protos.peer.ChaincodeID;\nimport org.hyperledger.fabric.protos.peer.ChaincodeMessage;\nimport org.hyperledger.fabric.protos.peer.ChaincodeSupportGrpc;\nimport org.hyperledger.fabric.shim.ChaincodeBase;\nimport org.hyperledger.fabric.shim.ChaincodeStub;\nimport org.hyperledger.fabric.shim.ResponseUtils;\nimport org.hyperledger.fabric.shim.impl.ChaincodeSupportClient;\nimport org.hyperledger.fabric.shim.impl.InvocationTaskManager;\nimport org.hyperledger.fabric.traces.Traces;\nimport org.junit.jupiter.api.Test;\n\nfinal class OpenTelemetryTracesProviderTest {\n\n    private final class ContextGetterChaincode extends ChaincodeBase {\n\n        @Override\n        public Response init(final ChaincodeStub stub) {\n            return ResponseUtils.newSuccessResponse();\n        }\n\n        @Override\n        public Response invoke(final ChaincodeStub stub) {\n            return ResponseUtils.newSuccessResponse(\"OK response\");\n        }\n\n        @Override\n        public Properties getChaincodeConfig() {\n            return new Properties();\n        }\n    }\n\n    @Test\n    void testProvider() {\n        OpenTelemetryTracesProvider provider = new OpenTelemetryTracesProvider();\n        provider.initialize(new Properties());\n        ChaincodeStub stub = new ChaincodeStubNaiveImpl();\n        Span span = provider.createSpan(stub);\n        assertThat(span.isRecording()).isTrue();\n        assertThat(provider.createInterceptor()).isNotNull();\n    }\n\n    @Test\n    void testTracing() throws Exception {\n\n        Properties props = new Properties();\n        props.put(\"CHAINCODE_TRACES_ENABLED\", \"true\");\n        props.put(\"CHAINCODE_TRACES_PROVIDER\", OpenTelemetryTracesProvider.class.getName());\n        props.put(\"OTEL_TRACES_SAMPLER\", \"always_on\");\n        props.put(\"OTEL_BSP_SCHEDULE_DELAY\", \"100\");\n        props.put(\"otel.traces.exporter\", \"TestSpanExporterProvider\");\n        Traces.initialize(props);\n        Metrics.initialize(props);\n\n        // set up a grpc server in process\n        ServerCallHandler<ChaincodeMessage, ChaincodeMessage> handler = (call, headers) -> {\n            call.close(Status.OK, headers);\n            return new ServerCall.Listener<>() {};\n        };\n\n        ServerServiceDefinition.Builder builder = ServerServiceDefinition.builder(ChaincodeGrpc.getServiceDescriptor())\n                .addMethod(ServerMethodDefinition.create(ChaincodeGrpc.getConnectMethod(), handler));\n        ServerServiceDefinition.Builder supportBuilder = ServerServiceDefinition.builder(\n                        ChaincodeSupportGrpc.getServiceDescriptor())\n                .addMethod(ServerMethodDefinition.create(ChaincodeSupportGrpc.getRegisterMethod(), handler));\n\n        String uniqueName = InProcessServerBuilder.generateName();\n        Server server = InProcessServerBuilder.forName(uniqueName)\n                .directExecutor()\n                .addService(builder.build())\n                .addService(supportBuilder.build())\n                .build()\n                .start();\n\n        // create our client\n        ManagedChannelBuilder<?> channelBuilder = InProcessChannelBuilder.forName(uniqueName);\n        ContextGetterChaincode chaincode = new ContextGetterChaincode();\n        ChaincodeSupportClient chaincodeSupportClient = new ChaincodeSupportClient(channelBuilder);\n\n        InvocationTaskManager itm = InvocationTaskManager.getManager(\n                chaincode, ChaincodeID.newBuilder().setName(\"foo\").build());\n\n        CompletableFuture<Void> wait = new CompletableFuture<>();\n        StreamObserver<ChaincodeMessage> requestObserver = chaincodeSupportClient\n                .getStub()\n                .register(new StreamObserver<>() {\n                    @Override\n                    public void onNext(final ChaincodeMessage chaincodeMessage) {\n                        // message off to the ITM...\n                        itm.onChaincodeMessage(chaincodeMessage);\n                    }\n\n                    @Override\n                    public void onError(final Throwable t) {\n                        chaincodeSupportClient.shutdown(itm);\n                        wait.completeExceptionally(t);\n                    }\n\n                    @Override\n                    public void onCompleted() {\n                        chaincodeSupportClient.shutdown(itm);\n                        wait.complete(null);\n                    }\n                });\n\n        chaincodeSupportClient.start(itm, requestObserver);\n        wait.get(5, TimeUnit.SECONDS);\n        Thread.sleep(5000);\n        List<SpanData> spans = TestSpanExporterProvider.SPANS;\n        assertThat(spans.isEmpty()).isFalse();\n\n        chaincodeSupportClient.shutdown(itm);\n        server.shutdown();\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/traces/impl/TestSpanExporterProvider.java",
    "content": "/*\n * Copyright 2019 IBM All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\npackage org.hyperledger.fabric.traces.impl;\n\nimport io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;\nimport io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider;\nimport io.opentelemetry.sdk.common.CompletableResultCode;\nimport io.opentelemetry.sdk.trace.data.SpanData;\nimport io.opentelemetry.sdk.trace.export.SpanExporter;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\n\npublic final class TestSpanExporterProvider implements ConfigurableSpanExporterProvider {\n\n    public static final List<SpanData> SPANS = new ArrayList<>();\n    public static final SpanExporter EXPORTER = new SpanExporter() {\n\n        @Override\n        public CompletableResultCode export(final Collection<SpanData> spans) {\n            SPANS.addAll(spans);\n            return CompletableResultCode.ofSuccess();\n        }\n\n        @Override\n        public CompletableResultCode flush() {\n            return CompletableResultCode.ofSuccess();\n        }\n\n        @Override\n        public CompletableResultCode shutdown() {\n            return CompletableResultCode.ofSuccess();\n        }\n    };\n\n    @Override\n    public SpanExporter createExporter(final ConfigProperties config) {\n        return EXPORTER;\n    }\n\n    @Override\n    public String getName() {\n        return \"TestSpanExporterProvider\";\n    }\n}\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider",
    "content": "org.hyperledger.fabric.traces.impl.TestSpanExporterProvider"
  },
  {
    "path": "fabric-chaincode-shim/src/test/resources/ca.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIICSTCCAe+gAwIBAgIQZ97pJjwOf+/15wXlaQhswTAKBggqhkjOPQQDAjB2MQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEfMB0GA1UEAxMWdGxz\nY2Eub3JnMS5leGFtcGxlLmNvbTAeFw0xODA4MjExNDEyMzhaFw0yODA4MTgxNDEy\nMzhaMHYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQH\nEw1TYW4gRnJhbmNpc2NvMRkwFwYDVQQKExBvcmcxLmV4YW1wbGUuY29tMR8wHQYD\nVQQDExZ0bHNjYS5vcmcxLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D\nAQcDQgAEgClmvqBKTmruqxNluLAL82p/06D58M6sg/5Qa6epl4/pjc7xv2KpDqIl\nONITgmKzR8VslccRoOpV97PRQljH8qNfMF0wDgYDVR0PAQH/BAQDAgGmMA8GA1Ud\nJQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zApBgNVHQ4EIgQgmGlEDIWlK8zX\nHz3tNOuC1jE58I8yNMaaIiz2fLaopMYwCgYIKoZIzj0EAwIDSAAwRQIhAPSWUrs3\nn0Lr6gfaYIxxfEopUm8/J8OVL8cdXPWFnkBbAiBFCCbgtxQRdvPUAHfJLtgOTNwM\nMxxvehamsJdpqCUsNA==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/resources/client.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIICOjCCAeGgAwIBAgIQCSag4gNL7SdBHpN3BtqTeDAKBggqhkjOPQQDAjB2MQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEfMB0GA1UEAxMWdGxz\nY2Eub3JnMS5leGFtcGxlLmNvbTAeFw0xODA4MjExNDEyMzhaFw0yODA4MTgxNDEy\nMzhaMFsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQH\nEw1TYW4gRnJhbmNpc2NvMR8wHQYDVQQDDBZVc2VyMUBvcmcxLmV4YW1wbGUuY29t\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEzh25F4EJhycT7wKoLRYZt/1rgsaW\n4yIPb+QnDg17jX/fhKSnFRcWE4U0OOmwESKc0MniMWxrdzUIYh+9W0DHPKNsMGow\nDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAM\nBgNVHRMBAf8EAjAAMCsGA1UdIwQkMCKAIJhpRAyFpSvM1x897TTrgtYxOfCPMjTG\nmiIs9ny2qKTGMAoGCCqGSM49BAMCA0cAMEQCICG6fm4B9BKFfWyLDOwpBOk/KRrI\nMqJdlNIFI6d6924wAiB4drv3HQCleeVOg2z9Mm4xflcgl78BsYduECh1+qcEqg==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/resources/client.crt.enc",
    "content": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNPakNDQWVHZ0F3SUJBZ0lRQ1NhZzRnTkw3U2RCSHBOM0J0cVRlREFLQmdncWhrak9QUVFEQWpCMk1Rc3cKQ1FZRFZRUUdFd0pWVXpFVE1CRUdBMVVFQ0JNS1EyRnNhV1p2Y201cFlURVdNQlFHQTFVRUJ4TU5VMkZ1SUVaeQpZVzVqYVhOamJ6RVpNQmNHQTFVRUNoTVFiM0puTVM1bGVHRnRjR3hsTG1OdmJURWZNQjBHQTFVRUF4TVdkR3h6ClkyRXViM0puTVM1bGVHRnRjR3hsTG1OdmJUQWVGdzB4T0RBNE1qRXhOREV5TXpoYUZ3MHlPREE0TVRneE5ERXkKTXpoYU1Gc3hDekFKQmdOVkJBWVRBbFZUTVJNd0VRWURWUVFJRXdwRFlXeHBabTl5Ym1saE1SWXdGQVlEVlFRSApFdzFUWVc0Z1JuSmhibU5wYzJOdk1SOHdIUVlEVlFRRERCWlZjMlZ5TVVCdmNtY3hMbVY0WVcxd2JHVXVZMjl0Ck1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXpoMjVGNEVKaHljVDd3S29MUlladC8xcmdzYVcKNHlJUGIrUW5EZzE3algvZmhLU25GUmNXRTRVME9PbXdFU0tjME1uaU1XeHJkelVJWWgrOVcwREhQS05zTUdvdwpEZ1lEVlIwUEFRSC9CQVFEQWdXZ01CMEdBMVVkSlFRV01CUUdDQ3NHQVFVRkJ3TUJCZ2dyQmdFRkJRY0RBakFNCkJnTlZIUk1CQWY4RUFqQUFNQ3NHQTFVZEl3UWtNQ0tBSUpocFJBeUZwU3ZNMXg4OTdUVHJndFl4T2ZDUE1qVEcKbWlJczlueTJxS1RHTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUNHNmZtNEI5QktGZld5TERPd3BCT2svS1JySQpNcUpkbE5JRkk2ZDY5MjR3QWlCNGRydjNIUUNsZWVWT2cyejlNbTR4ZmxjZ2w3OEJzWWR1RUNoMStxY0VxZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
  },
  {
    "path": "fabric-chaincode-shim/src/test/resources/client.key",
    "content": "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgwCm9EFOOwAugpN3s\nleXGaKAzrr1E/0PJbqh8p2/MqnyhRANCAATOHbkXgQmHJxPvAqgtFhm3/WuCxpbj\nIg9v5CcODXuNf9+EpKcVFxYThTQ46bARIpzQyeIxbGt3NQhiH71bQMc8\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "fabric-chaincode-shim/src/test/resources/client.key.enc",
    "content": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR0hBZ0VBTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEJHMHdhd0lCQVFRZ3dDbTlFRk9Pd0F1Z3BOM3MKbGVYR2FLQXpycjFFLzBQSmJxaDhwMi9NcW55aFJBTkNBQVRPSGJrWGdRbUhKeFB2QXFndEZobTMvV3VDeHBiagpJZzl2NUNjT0RYdU5mOStFcEtjVkZ4WVRoVFE0NmJBUklwelF5ZUl4Ykd0M05RaGlINzFiUU1jOAotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg=="
  },
  {
    "path": "fabric-chaincode-shim/src/test/resources/client.key.password-protected",
    "content": "-----BEGIN ENCRYPTED PRIVATE KEY-----\nMIGxMBwGCiqGSIb3DQEMAQMwDgQIfzm0IqTm+rACAggABIGQDY1vpaSD+KDuVRyT\nGi35536iOYUuVoz01ktV3YCDv03Pm5+8xZ1JXXW8lDM3JP/TcKbocRRk63y/R7O2\ndB9kcyV7/gYtYH0B3TMk1/x1WtfHL8JnYRFHQ/OuhYjJ6O04B4aY2waeYByzsIsI\nYhNVZq5fZ7/bjsy8b54o57WD4DDHH3uRysbv8I5TaDVyJMJq\n-----END ENCRYPTED PRIVATE KEY-----\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-9.4.1-bin.zip\nnetworkTimeout=10000\nvalidateDistributionUrl=true\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n# SPDX-License-Identifier: Apache-2.0\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\n# This is normally unused\n# shellcheck disable=SC2034\nAPP_BASE_NAME=${0##*/}\n# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)\nAPP_HOME=$( cd -P \"${APP_HOME:-./}\" > /dev/null && printf '%s\\n' \"$PWD\" ) || exit\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    if ! command -v java >/dev/null 2>&1\n    then\n        die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Collect all arguments for the java command:\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,\n#     and any embedded shellness will be escaped.\n#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be\n#     treated as '${Hostname}' itself on the command line.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -jar \"$APP_HOME/gradle/wrapper/gradle-wrapper.jar\" \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n@rem SPDX-License-Identifier: Apache-2.0\r\n@rem\r\n\r\n@if \"%DEBUG%\"==\"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\r\n@rem This is normally unused\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif %ERRORLEVEL% equ 0 goto execute\r\n\r\necho. 1>&2\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2\r\necho. 1>&2\r\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\r\necho location of your Java installation. 1>&2\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho. 1>&2\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2\r\necho. 1>&2\r\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\r\necho location of your Java installation. 1>&2\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -jar \"%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\" %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif %ERRORLEVEL% equ 0 goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nset EXIT_CODE=%ERRORLEVEL%\r\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\r\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\r\nexit /b %EXIT_CODE%\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "pmd-ruleset.xml",
    "content": "<?xml version=\"1.0\"?>\r\n<ruleset name=\"Fabric Chaincode Java rules\"\r\n         xmlns=\"http://pmd.sourceforge.net/ruleset/2.0.0\"\r\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n         xsi:schemaLocation=\"http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd\">\r\n    <description>Custom PMD ruleset</description>\r\n    <rule ref=\"category/java/bestpractices.xml\">\r\n        <exclude name=\"UseVarargs\"/>\r\n    </rule>\r\n    <rule ref=\"category/java/bestpractices.xml/LooseCoupling\">\r\n        <properties>\r\n            <property name=\"allowedTypes\" value=\"java.util.Properties,org.hyperledger.fabric.contract.metadata.TypeSchema\"/>\r\n        </properties>\r\n    </rule>\r\n    <rule ref=\"category/java/codestyle.xml\">\r\n        <exclude name=\"AtLeastOneConstructor\"/>\r\n        <exclude name=\"CommentDefaultAccessModifier\"/>\r\n        <exclude name=\"LocalVariableCouldBeFinal\"/>\r\n        <exclude name=\"LongVariable\"/>\r\n        <exclude name=\"OnlyOneReturn\"/>\r\n        <exclude name=\"ShortVariable\"/>\r\n        <exclude name=\"TooManyStaticImports\"/>\r\n    </rule>\r\n    <rule ref=\"category/java/codestyle.xml/UseExplicitTypes\">\r\n        <properties>\r\n            <property name=\"allowLiterals\" value=\"true\"/>\r\n            <property name=\"allowCtors\" value=\"true\"/>\r\n        </properties>\r\n    </rule>\r\n    <rule ref=\"category/java/design.xml\">\r\n        <exclude name=\"CouplingBetweenObjects\"/>\r\n        <exclude name=\"DataClass\"/>\r\n        <exclude name=\"ExcessiveImports\"/>\r\n        <exclude name=\"LoosePackageCoupling\"/>\r\n        <exclude name=\"TooManyMethods\"/>\r\n    </rule>\r\n    <rule ref=\"category/java/design.xml/LawOfDemeter\">\r\n        <properties>\r\n            <property name=\"trustRadius\" value=\"3\"/>\r\n        </properties>\r\n    </rule>\r\n    <rule ref=\"category/java/documentation.xml/UncommentedEmptyConstructor\"/>\r\n    <rule ref=\"category/java/documentation.xml/UncommentedEmptyMethodBody\"/>\r\n    <rule ref=\"category/java/errorprone.xml\">\r\n        <exclude name=\"AvoidFieldNameMatchingMethodName\"/>\r\n        <exclude name=\"UseProperClassLoader\"/>\r\n    </rule>\r\n    <rule ref=\"category/java/multithreading.xml\">\r\n        <exclude name=\"DoNotUseThreads\"/>\r\n        <exclude name=\"UseConcurrentHashMap\"/>\r\n    </rule>\r\n    <rule ref=\"category/java/performance.xml\"/>\r\n    <rule ref=\"category/java/security.xml\"/>\r\n</ruleset>\r\n"
  },
  {
    "path": "release_notes/v1.3.0.txt",
    "content": "v1.3.0 September 25, 2018\n-------------------------\n\nRelease Notes\n-------------\nInitial release of Java chaincode support.\n\nbaseimage version 0.4.12\nJava version 1.8.0_sr5fp21\n\nKnown Vulnerabilities\n---------------------\nnone\n\nResolved Vulnerabilities\n------------------------\nnone\n\nKnown Issues & Workarounds\n--------------------------\nnone\n\nChange Log\n----------\nhttps://github.com/hyperledger/fabric-chaincode-java/blob/master/CHANGELOG.md#v130-rc1\n"
  },
  {
    "path": "release_notes/v1.4.0.txt",
    "content": "v1.4.0-rc1 December 11, 2018\n----------------------------\n\nRelease Notes\n-------------\nJava chaincode v1.4.0 adds parity with Go chaincode:\nFAB-12329 State-based endorsement support\nFAB-12328 Query result pagination support\n\nIncrease test coverage, including integration tests based on\ntestcontainers framework.\n\nbaseimage version: 0.4.14\nJava version:      openjdk version \"1.8.0_181\"\n\nKnown Vulnerabilities\n---------------------\nnone\n\nResolved Vulnerabilities\n------------------------\nnone\n\nKnown Issues & Workarounds\n--------------------------\nnone\n\nChange Log\n----------\nhttps://github.com/hyperledger/fabric-chaincode-java/blob/master/CHANGELOG.md#v140-rc1\n"
  },
  {
    "path": "release_notes/v2.0.0-alpha.txt",
    "content": "v2.0.0-alpha April 9, 2019\n--------------------------\n\nRelease Notes\n-------------\nJava chaincode v2.0.0-alpha includes multiple improvements:\n\nJavaenv docker images is now based on Alpine to reduce the size.\nIntegration tests have been improved.\nJava chaincode extra validation during start.\nAdded support for maven projects.\n\nopenjdk:8-slim is now used instead of baseimage for the basis of javaenv Docker image.\nJava version:      openjdk version \"1.8.0_181\"\n\nKnown Vulnerabilities\n---------------------\nnone\n\nResolved Vulnerabilities\n------------------------\nnone\n\nKnown Issues & Workarounds\n--------------------------\nnone\n\nChange Log\n----------\nhttps://github.com/hyperledger/fabric-chaincode-java/blob/master/CHANGELOG.md#v200-alpha\n"
  },
  {
    "path": "release_notes/v2.0.0-beta.txt",
    "content": "v2.0.0-beta December 12, 2019\n--------------------------\n\nRelease Notes\n-------------\nJava chaincode v2.0.0-alpha includes multiple improvements:\n\nJavaenv docker images is now based on Alpine to reduce the size.\nIntegration tests have been improved.\nJava chaincode extra validation during start.\nAdded support for maven projects.\n\nadoptopenjdk/openjdk11:jdk-11.0.4_11-alpine is now used instead of baseimage for the basis of javaenv Docker image.\n\nKnown Vulnerabilities\n---------------------\nnone\n\nResolved Vulnerabilities\n------------------------\nnone\n\nKnown Issues & Workarounds\n--------------------------\nnone\n\nChange Log\n----------\nhttps://github.com/hyperledger/fabric-chaincode-java/blob/master/CHANGELOG.md#v200-beta\n"
  },
  {
    "path": "release_notes/v2.0.0.txt",
    "content": "v2.0.0 20 January 2020\n--------------------------\n\nRelease Notes\n-------------\nJava chaincode v2.0.0 includes multiple improvements:\n\nJavaenv docker images is now based on Alpine to reduce the size.\nIntegration tests have been improved.\nJava chaincode extra validation during start.\nAdded support for maven projects.\n\nadoptopenjdk/openjdk11:jdk-11.0.4_11-alpine is now used instead of baseimage for the basis of javaenv Docker image.\n\nKnown Vulnerabilities\n---------------------\nnone\n\nResolved Vulnerabilities\n------------------------\nnone\n\nKnown Issues & Workarounds\n--------------------------\nnone\n\nChange Log\n----------\nhttps://github.com/hyperledger/fabric-chaincode-java/blob/master/CHANGELOG.md#v200"
  },
  {
    "path": "release_notes/v2.0.1.txt",
    "content": "v2.0.1 4 March 2020\n--------------------------\n\nRelease Notes\n-------------\n\n- Provides access to the localmspid\n\nadoptopenjdk/openjdk11:jdk-11.0.4_11-alpine is now used for the basis of javaenv Docker image.\n\nKnown Vulnerabilities\n---------------------\nnone\n\nResolved Vulnerabilities\n------------------------\nnone\n\nKnown Issues & Workarounds\n--------------------------\nnone\n\nChange Log\n----------\nhttps://github.com/hyperledger/fabric-chaincode-java/blob/master/CHANGELOG.md#v201"
  },
  {
    "path": "release_notes/v2.1.0.txt",
    "content": "v2.1.0 4 March 2020\n--------------------------\n\nRelease Notes\n-------------\nThere are minimal changes between v2.0.0 and v2.1.0, please see the change log for a full list of updates.\n\nThe release-2.0 branch has been renamed to release-2.x; the v2.1.0 release supercedes v2.0.0.\nThe release-1.4 branch is currently LTS, please see the proposed Fabric LTS strategy for more information:\nhttps://github.com/hyperledger/fabric-rfcs/pull/23\n\nKnown Vulnerabilities\n---------------------\nnone\n\nResolved Vulnerabilities\n------------------------\nnone\n\nKnown Issues & Workarounds\n--------------------------\nnone\n\nChange Log\n----------\nhttps://github.com/hyperledger/fabric-chaincode-java/blob/release-2.x/CHANGELOG.md#v210\n"
  },
  {
    "path": "release_notes/v2.1.1.txt",
    "content": "v2.1.1 18 May 2020\n--------------------------\n\nRelease Notes\n-------------\nThis is a bug fix release with a fix for a performance issue when using query.\n\nSee this JIRA for more information https://jira.hyperledger.org/browse/FABCJ-285\n\nThe release-2.0 branch has been renamed to release-2.x; the v2.1.0 release supercedes v2.0.0.\nThe release-1.4 branch is currently LTS, please see the proposed Fabric LTS strategy for more information:\nhttps://github.com/hyperledger/fabric-rfcs/pull/23\n\nKnown Vulnerabilities\n---------------------\nnone\n\nResolved Vulnerabilities\n------------------------\nnone\n\nKnown Issues & Workarounds\n--------------------------\nnone\n\nChange Log\n----------\nhttps://github.com/hyperledger/fabric-chaincode-java/blob/release-2.x/CHANGELOG.md#v211\n"
  },
  {
    "path": "release_notes/v2.2.0.txt",
    "content": "v2.2.0 \n--------------------------\n\nRelease Notes\n-------------\nThis v2.2.0 Release is the LTS version of the fabric-chaincode-java\n\nKnown Vulnerabilities\n---------------------\nnone\n\nResolved Vulnerabilities\n------------------------\nnone\n\nKnown Issues & Workarounds\n--------------------------\nnone\n\nChange Log\n----------\nhttps://github.com/hyperledger/fabric-chaincode-java/blob/release-2.x/CHANGELOG.md#v220\n"
  },
  {
    "path": "release_notes/v2.2.1.txt",
    "content": "v2.2.1 \n--------------------------\n\nRelease Notes\n-------------\nThis v2.2.1 Release is the LTS version of the fabric-chaincode-java\n\nKnown Vulnerabilities\n---------------------\nnone\n\nResolved Vulnerabilities\n------------------------\nnone\n\nKnown Issues & Workarounds\n--------------------------\nnone\n\nChange Log\n----------\nhttps://github.com/hyperledger/fabric-chaincode-java/blob/release-2.x/CHANGELOG.md#v221"
  },
  {
    "path": "release_notes/v2.3.0.txt",
    "content": "v2.3.0 \n--------------------------\n\nRelease Notes\n-------------\nThis v2.3.0 Release is the LTS version of the fabric-chaincode-java\n\nKnown Vulnerabilities\n---------------------\nnone\n\nResolved Vulnerabilities\n------------------------\nnone\n\nKnown Issues & Workarounds\n--------------------------\nnone\n\nChange Log\n----------\nhttps://github.com/hyperledger/fabric-chaincode-java/blob/release-2.x/CHANGELOG.md#v221"
  },
  {
    "path": "release_notes/v2.3.1.txt",
    "content": "v2.3.1 \n--------------------------\n\nRelease Notes\n-------------\nThis v2.3.1 Release is a bug fix release of the main branch.\n\nKnown Vulnerabilities\n---------------------\nnone\n\nResolved Vulnerabilities\n------------------------\nnone\n\nKnown Issues & Workarounds\n--------------------------\nnone\n\nChange Log\n----------\nhttps://github.com/hyperledger/fabric-chaincode-java/blob/release-2.x/CHANGELOG.md#v231"
  },
  {
    "path": "release_notes/v2.4.0-beta.txt",
    "content": "v2.4.0-beta\n--------------------------\n\nRelease Notes\n-------------\nThis v2.4.0-beta Release is a bug fix release of the main branch.\n\nKnown Vulnerabilities\n---------------------\nnone\n\nResolved Vulnerabilities\n------------------------\nnone\n\nKnown Issues & Workarounds\n--------------------------\nnone\n\nChange Log\n----------\nhttps://github.com/hyperledger/fabric-chaincode-java/blob/release-2.x/CHANGELOG.md#v240\n"
  },
  {
    "path": "release_notes/v2.4.0.txt",
    "content": "v2.4.0\n--------------------------\n\nRelease Notes\n-------------\nThis v2.4.0 Release is to support the Fabric v2.4 release. \n\nKnown Vulnerabilities\n---------------------\nnone\n\nResolved Vulnerabilities\n------------------------\nnone\n\nKnown Issues & Workarounds\n--------------------------\nnone\n\nChange Log\n----------\nhttps://github.com/hyperledger/fabric-chaincode-java/blob/release-2.x/CHANGELOG.md#v240\n"
  },
  {
    "path": "release_notes/v2.4.1.txt",
    "content": "v2.4.1\n--------------------------\n\nRelease Notes\n-------------\nThis release improves support for the chaincode-as-a-service feature. It removes the need to write custom 'bootstrap' scripts\nSee the `examples/fabric-contract-examples-as-service`\n\nKnown Vulnerabilities\n---------------------\nnone\n\nResolved Vulnerabilities\n------------------------\nnone\n\nKnown Issues & Workarounds\n--------------------------\nnone\n\nChange Log\n----------\nhttps://github.com/hyperledger/fabric-chaincode-java/blob/release-2.x/CHANGELOG.md#v241\n"
  },
  {
    "path": "release_notes/v2.5.0.txt",
    "content": "v2.5.0 LTS\n----------\n\nRelease Notes\n-------------\nThis is the LTS Release of of the v2.5 Fabric Chaincode Java. It replaces the previous v2.2 LTS.\n\n- the default `JavaEnv` docker image has been moved to use the Eclipse Temurin Java 11 JDK\n- the PurgePrivateData feature is exposed via a new `PurgePrivateData` API \n\n\nKnown Vulnerabilities\n---------------------\nnone\n\nResolved Vulnerabilities\n------------------------\nnone\n\nKnown Issues & Workarounds\n--------------------------\nnone\n\nChange Log\n----------\nhttps://github.com/hyperledger/fabric-chaincode-java/blob/release-2.x/CHANGELOG.md#v250\n"
  },
  {
    "path": "settings.gradle",
    "content": "/*\n * Copyright IBM Corp. 2017 All Rights Reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\nrootProject.name = 'fabric-chaincode-java'\n\ninclude 'fabric-chaincode-shim'\ninclude 'fabric-chaincode-docker'\ninclude 'fabric-chaincode-integration-test'\n"
  }
]