[
  {
    "path": ".circleci/config.yml",
    "content": "version: 2\njobs:\n  build:\n    docker:\n      - image: springcloud/pipeline-base\n        user: appuser\n    environment:\n      _JAVA_OPTIONS: \"-Xms1024m -Xmx2048m\"\n      TERM: dumb\n    branches:\n      ignore:\n        - gh-pages # list of branches to ignore\n    resource_class: medium\n    steps:\n      - checkout\n      - restore_cache:\n          key: sc-alibaba-{{ .Branch }}\n      - run:\n          name: \"Download dependencies\"\n          command: ./mvnw -Pspring -U --fail-never dependency:go-offline || true\n      - save_cache:\n          key: sc-alibaba-{{ .Branch }}\n          paths:\n            - ~/.m2\n      - run:\n          name: \"Running build\"\n          command: ./mvnw clean install -U -nsu --batch-mode -Dmaven.test.redirectTestOutputToFile=true -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -Dgpg.skip\n      - run:\n          name: \"Aggregate test results\"\n          when: always\n          command: |\n            mkdir -p ~/junit/\n            find . -type f -regex \".*/target/.*-reports/.*\" -exec cp {} ~/junit/ \\;\n            bash <(curl -s https://codecov.io/bash)\n      - store_artifacts:\n          path: ~/junit/\n          destination: artifacts\n      - store_test_results:\n          path: ~/junit/\n          destination: testartifacts"
  },
  {
    "path": ".codecov.yml",
    "content": "\ncoverage:\n  status:\n    project: off\n    patch: off"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*.java]\nindent_style = tab\nindent_size = 4\ncontinuation_indent_size = 8\n\n[*.groovy]\nindent_style = tab\nindent_size = 4\ncontinuation_indent_size = 8\n\n[*.xml]\nindent_style = tab\nindent_size = 4\ncontinuation_indent_size = 8\n\n[*.yml]\nindent_style = space\nindent_size = 2\n\n[*.yaml]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n我们鼓励使用英文，如果不能直接使用，可以使用翻译软件，您仍旧可以保留中文原文。另外请按照如下要求提交相关信息节省社区维护同学的理解成本，否则该讨论极有可能直接被忽视或关闭。\nWe recommend using English. If you are non-native English speaker, you can use the translation software. We recommend using English. If you are non-native English speaker, you can use the translation software. In addition, please submit relevant information according to the following requirements to save the understanding cost of community maintenances, otherwise the discussion is very likely to be ignored or closed directly.\n\n\n**Which Component**\neg. Nacos Discovery, Sentinel\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**Simplest demo**\nThe URL of the simplest demo to reproduce the problem.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Additional context**\nAdd any other context about the problem here.\ne.g.  MacOS  、Java8 、 Version 0.2.1.RELEASE\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n我们鼓励使用英文，如果不能直接使用，可以使用翻译软件，您仍旧可以保留中文原文。另外请按照如下要求提交相关信息节省社区维护同学的理解成本，否则该讨论极有可能直接被忽视或关闭。\nWe recommend using English. If you are non-native English speaker, you can use the translation software. In addition, please submit relevant information according to the following requirements to save the understanding cost of community maintenances, otherwise the discussion is very likely to be ignored or closed directly.\n\n\n**Which Component**\neg. Nacos Discovery, Sentinel\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.md",
    "content": "---\nname: Question\nabout: how to ask a valid question\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n我们鼓励使用英文，如果不能直接使用，可以使用翻译软件，您仍旧可以保留中文原文。另外请按照如下要求提交相关信息节省社区维护同学的理解成本，否则该讨论极有可能直接被忽视或关闭。\nWe recommend using English. If you are non-native English speaker, you can use the translation software. We recommend using English. If you are non-native English speaker, you can use the translation software. In addition, please submit relevant information according to the following requirements to save the understanding cost of community maintenances, otherwise the discussion is very likely to be ignored or closed directly.\n\n\n\n**Which Component**\neg. Nacos Discovery, Sentinel\n\n**Describe what problem you have encountered**\nA clear and concise description of what you want to do.\n\n**Describe what information you have read**\neg. I have read the reference doc of Sentinel\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "\n### Describe what this PR does / why we need it\n\n\n### Does this pull request fix one issue?\n\n<!--If that, add \"Fixes #xxxx\" below in the next line. For example, Fixes #15. Otherwise, add \"NONE\" -->\n\n### Describe how you did it\n\n\n### Describe how to verify it\n\n\n### Special notes for reviews\n"
  },
  {
    "path": ".github/dependbot.yml",
    "content": "# `dependabot.yml` file with\n# maven version update.\n\nversion: 2\nupdates:\n\n  - package-ecosystem: \"maven\"\n    directory: \"/\"\n    open-pull-requests-limit: 20\n    # Ignore major version updates\n    ignore:\n      - dependency-name: \"*\"\n        update-types: [\"version-update:semver-major\"]\n    schedule:\n      interval: \"weekly\"\n      day: \"monday\"\n      time: \"03:00\"\n      timezone: \"US/Eastern\"\n"
  },
  {
    "path": ".github/labels.yml",
    "content": "area:\n  - 'ai'\n  - 'ci'\n  - 'nacos'\n  - 'sentinel'\n  - 'rocketmq'\n  - 'community'\n  - 'example'\n  - 'seata'\n  - 'openSergo'\n  - 'spring cloud'\n  - 'testing'\n\nkind:\n  - 'bug'\n  - 'chore'\n  - 'discussion'\n  - 'documention'\n  - 'question'\n  - 'refactor'\n  - 'invalid'\n  - 'enhancement'\n  \n"
  },
  {
    "path": ".github/workflows/github-packages-release.yml",
    "content": "name: GitHub Packages Release\non:\n  push:\n    branches:\n      - 2023.x\n      - 2025.0.x\n      - 2025.1.x\njobs:\n  release:\n    name: Release\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Set up JDK 17\n        uses: actions/setup-java@v4\n        with:\n          java-version: '17'\n          distribution: 'adopt'\n      - name: Dependencies Cache\n        uses: actions/cache@v4\n        with:\n          path: ~/.m2/repository\n          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}\n          restore-keys: |\n            ${{ runner.os }}-maven-\n      - name: install dependencies\n        run: mvn clean -B install -U package -pl '!spring-cloud-alibaba-coverage'  -DskipTests\n      - name: cat ~/.m2/settings.xml\n        run: |\n          cat ~/.m2/settings.xml\n      - name: Deploy to GitHub Package Maven\n        run: |\n          VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)\n          echo \"Project version: $VERSION\"\n          if [[ \"$VERSION\" != *\"-SNAPSHOT\" ]]; then\n            echo \"Not a snapshot version. Skipping deployment.\"\n            exit 0\n          fi\n          mvn clean -B deploy -pl . -DskipTests\n          cd $GITHUB_WORKSPACE/spring-cloud-alibaba-dependencies\n          mvn clean -B deploy -DskipTests\n          cd $GITHUB_WORKSPACE/spring-cloud-alibaba-starters\n          mvn clean -B deploy -DskipTests\n        env:\n          GITHUB_TOKEN: ${{ github.token }}\n      - name: Delete snapshots from the Maven local repository\n        run: find ~/.m2/repository -type d -name '*-SNAPSHOT' -print -exec rm -r {} +\n"
  },
  {
    "path": ".github/workflows/integration-test.yml",
    "content": "name: Integration Testing\non:\n  push:\n    branches:\n      - 2023.x\n      - 2025.0.x\n      - 2025.1.x\n  pull_request:\n    branches:\n      - 2023.x\n      - 2025.0.x\n      - 2025.1.x\njobs:\n  deploy-docker-image:\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    steps:\n      - name: Check out the repo\n        uses: actions/checkout@v4\n\n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@v1\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v1\n\n  integration-testing:\n    name: Integration Testing\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Set up JDK 17\n        uses: actions/setup-java@v4\n        with:\n          java-version: '17'\n          distribution: 'adopt'\n      - name: Dependencies Cache\n        uses: actions/cache@v4\n        with:\n          path: ~/.m2/repository\n          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}\n          restore-keys: |\n            ${{ runner.os }}-maven-\n      - name: Compile & Checkstyle\n        run: mvn clean -B compile\n      - name: install dependencies\n        run: mvn clean -B install -U package -pl '!spring-cloud-alibaba-coverage'  -DskipTests\n      - name: Testing\n        run: ./mvnw verify -B -Dmaven.test.skip=false\n#        run: mvn clean -Dit.enabled=true test\n      - name: Delete snapshots from the Maven local repository\n        run: find ~/.m2/repository -type d -name '*-SNAPSHOT' -print -exec rm -r {} +\n\n"
  },
  {
    "path": ".github/workflows/issue-command.yml",
    "content": "name: Issue and PR comment commands\n\npermissions: {}\n\non:\n  issue_comment:\n    types:\n      - created\n      - edited\n\njobs:\n  execute:\n    runs-on: ubuntu-latest\n    permissions:\n      issues: write\n      pull-requests: write\n    steps:\n      - uses: jpmcb/prow-github-actions@f4d01dd4b13f289014c23fe5a19878a2479cb35b  # v1.1.3\n        with:\n          prow-commands: '/assign\n            /unassign\n            /area\n            /kind\n            /priority\n            /remove\n            /close\n            /reopen\n            /lock\n            /milestone\n            /hold\n            /cc\n            /uncc'\n          github-token: \"${{ secrets.GITHUB_TOKEN }}\"\n\n"
  },
  {
    "path": ".github/workflows/md-link-check.yml",
    "content": "name: 'Link Checker'\n\n# **What it does**: Renders the content of every page and check all internal links.\n# **Why we have it**: To make sure all links connect correctly.\n# **Who does it impact**: Docs content.\n\non:\n  workflow_dispatch:\n  push:\n    # branches: [master, 'release/**']\n    paths:\n      - '**/*.md'\n      - '**/link-check.yml'\n  pull_request:\n    branches: [2023.x, 2025.0.x, 2025.1.x, \"release/**\"]\n    paths:\n      - '**/*.md'\n      - '**/link-check.yml'\n\npermissions:\n  contents: read\n  # Needed for the 'trilom/file-changes-action' action\n  pull-requests: read\n\n# This allows a subsequently queued workflow run to interrupt previous runs\nconcurrency:\n  group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'\n  cancel-in-progress: true\n\njobs:\n  check-links:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Get script\n        run: |\n          wget https://raw.githubusercontent.com/xuruidong/markdown-link-checker/main/link_checker.py\n\n      - name: Setup python\n        uses: actions/setup-python@v4\n        with:\n          python-version: '3.9'\n\n      - name: Link check (critical, all files)\n        run: |\n          # python link_checker.py ./ --enable-external --ignore \"http://apisix.iresty.com\" \"https://www.upyun.com\" \"https://github.com/apache/apisix/actions/workflows/build.yml/badge.svg\" \"https://httpbin.org/\" \"https://en.wikipedia.org/wiki/Cache\"\n          python link_checker.py ./\n"
  },
  {
    "path": ".github/workflows/stale.yml",
    "content": "name: \"Stale bot of marking stale issues\"\non:\n  schedule:\n    - cron: \"50 18 * * *\"\n\npermissions:\n  issues: write\n\njobs:\n  stale:\n    runs-on: ubuntu-latest\n    permissions:\n      issues: write\n      pull-requests: write\n    \n    steps:\n      - uses: actions/stale@v5\n        with:\n          repo-token: ${{ secrets.GITHUB_TOKEN }}\n          stale-issue-message: 'This issue has been open 30 days with no activity. This will be closed in 7 days.'\n          close-issue-message: \"This issue has been automatically marked as stale because it hasn't had any recent activity.If you think this should still be open, or the problem still persists, just pop a reply in the comments and one of the maintainers will (try!) to follow up. Thank you for your interest and contribution to the Sping Cloud Alibaba Community.\"\n          days-before-issue-stale: 30\n          days-before-issue-close: 7\n          stale-issue-label: \"stale\"\n          close-issue-label: \"wait-for-feedback\"\n          exempt-all-milestones: true\n          operations-per-run: 10\n          days-before-pr-stale: -1\n          days-before-pr-close: -1\n          exempt-issue-labels: discussion,bug,question,good first issue\n \n"
  },
  {
    "path": ".gitignore",
    "content": "# Compiled class file\n*.class\n*.classpath\n*.factorypath\n\n# Log file\n*.log\n\n# BlueJ files\n*.ctxt\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Package Files #\n*.jar\n!.mvn/wrapper/maven-wrapper.jar\n\n*.war\n*.ear\n*.zip\n*.tar.gz\n*.rar\n\n# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml\nhs_err_pid*\n\n# IDE Files #\n*.iml\n.idea\n.idea/\n.project\n.settings\ntarget\n.DS_Store\n.qoder\n.cursor\n.vscode\n\n#Seata test data file\nsessionStore/\n\n# temp ignore\n*.cache\n*.diff\n*.patch\n*.tmp\n\n# Maven ignore\n.flattened-pom.xml\n\n"
  },
  {
    "path": ".licenscheckconfig.yaml",
    "content": "header:\n  license:\n    spdx-id: Apache-2.0\n    copyright-owner: alibaba\n    content: |\n      Copyright 2013-2023 the original author or 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  paths-ignore:\n    - '.gitignore'\n    - '.gitattributes'\n    - '.travis.yml'\n    - 'codecov.yml'\n    - 'CONTRIBUTING.md'\n    - 'CONTRIBUTING_CN.md'\n    - 'CODE_OF_CONDUCT.md'\n    - 'README.md'\n    - 'LICENSE'\n    - 'NOTICE'\n    - '**/*.md'\n    - '.github/**'\n    - '**/*.yaml'\n    - \"**/*.yml\"\n    - '**/*.xml'\n    - '**/*.conf'\n    - '**/*.sql'\n    - '*.adoc'\n    - 'eclipse'\n    - '**/Dockerfile'\n    - '**/*.properties'\n    - '**/*.json'\n    - '**/*.html'\n    - \"spring-cloud-alibaba-examples/integrated-example/docker-compose/.env\"\n    #SPI、spring.factories、spring-configuration-metadata.json、additional-spring-configuration-metadata.json\n    - '**/src/test/resources/META-INF/**'\n    - '**/src/main/resources/META-INF/**'\n    - '**/target/**'\n    - '**/*.iml'\n    - 'mvnw'\n    - 'mvnw.cmd'\n    - '**/*.sh'\n    - '.mvn/**'\n    - 'sessionStore/**'\n    - 'distribution/LICENSE-BIN'\n    - 'distribution/NOTICE-BIN'\n    - 'test/src/test/resources/**'\n    - '**/src/test/resources/statelang/**'\n\n  comment: on-failure\ndependency:\n  files:\n    - pom.xml\n"
  },
  {
    "path": ".mvn/jvm.config",
    "content": "-Xmx1024m -XX:CICompilerCount=1 -XX:TieredStopAtLevel=1 -Djava.security.egd=file:/dev/./urandom"
  },
  {
    "path": ".mvn/wrapper/maven-wrapper.properties",
    "content": "# Copyright 2013-2023 the original author or 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\ndistributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.0/apache-maven-3.9.0-bin.zip\nwrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "## Contributor Code of Conduct\n\nAs contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.\n\nWe are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.\n\nExamples of unacceptable behavior by participants include:\n\n- The use of sexualized language or imagery\n\n- Personal attacks\n\n- Trolling or insulting/derogatory comments\n\n- Public or private harassment\n\n- Publishing other’s private information, such as physical or electronic addresses, without explicit permission\n\n- Other unethical or unprofessional conduct\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.\n\nBy adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.\n\nThis Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at spring-code-of-conduct@pivotal.io . All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident.\n\nThis Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org/), version 1.3.0, available at [contributor-covenant.org/version/1/3/0/](http://contributor-covenant.org/version/1/3/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"
  },
  {
    "path": "README-zh.md",
    "content": "# Spring Cloud Alibaba\n\n[![CircleCI](https://circleci.com/gh/alibaba/spring-cloud-alibaba/tree/2025.1.x.svg?style=svg)](https://circleci.com/gh/alibaba/spring-cloud-alibaba/tree/2025.1.x)\n[![Maven Central](https://img.shields.io/maven-central/v/com.alibaba.cloud/spring-cloud-alibaba-dependencies.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:com.alibaba.cloud%20AND%20a:spring-cloud-alibaba-dependencies)\n[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)\n[![actions](https://github.com/alibaba/spring-cloud-alibaba/workflows/Integration%20Testing/badge.svg)](https://github.com/alibaba/spring-cloud-alibaba/actions)\n[![Leaderboard](https://img.shields.io/badge/SCA-Check%20Your%20Contribution-orange)](https://opensource.alibaba.com/contribution_leaderboard/details?projectValue=sca)\n\nSpring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件，方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。\n\n依托 Spring Cloud Alibaba，您只需要添加一些注解和少量配置，就可以将 Spring Cloud 应用接入阿里微服务解决方案，通过阿里中间件来迅速搭建分布式应用系统。\n\n此外，阿里云同时还提供了 Spring Cloud Alibaba 企业版 [微服务解决方案](https://www.aliyun.com/product/aliware/mse?spm=github.spring.com.topbar)，包括无侵入服务治理(全链路灰度，无损上下线，离群实例摘除等)，企业级 Nacos 注册配置中心和企业级云原生网关等众多产品。\n\n参考文档 请查看 [WIKI](https://github.com/alibaba/spring-cloud-alibaba/wiki) 。\n\n为 Spring Cloud Alibaba 贡献代码请参考 [如何贡献](https://sca.aliyun.com/docs/developer/contributor-guide/new-contributor-guide_dev/) 。\n\n## 主要功能\n\n* **服务限流降级**：默认支持 WebServlet、WebFlux、OpenFeign、RestTemplate、Spring Cloud Gateway、Dubbo 和 RocketMQ 限流降级功能的接入，可以在运行时通过控制台实时修改限流降级规则，还支持查看限流降级 Metrics 监控。\n* **服务注册与发现**：适配 Spring Cloud 服务注册与发现标准，默认集成对应 Spring Cloud 版本所支持的负载均衡组件的适配。\n* **分布式配置管理**：支持分布式系统中的外部化配置，配置更改时自动刷新。\n* **消息驱动能力**：基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。\n* **分布式事务**：使用 @GlobalTransactional 注解， 高效并且对业务零侵入地解决分布式事务问题。\n* **阿里云对象存储**：阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。\n* **分布式任务调度**：提供秒级、精准、高可靠、高可用的定时（基于 Cron 表达式）任务调度服务。同时提供分布式的任务执行模型，如网格任务。网格任务支持海量子任务均匀分配到所有 Worker（schedulerx-client）上执行。\n* **阿里云短信服务**：覆盖全球的短信服务，友好、高效、智能的互联化通讯能力，帮助企业迅速搭建客户触达通道。\n\n\n更多功能请参考 [Roadmap](https://github.com/alibaba/spring-cloud-alibaba/blob/2025.1.x/Roadmap-zh.md)\n\n除了上述所具有的功能外，针对企业级用户的场景，Spring Cloud Alibaba 配套的企业版微服务治理方案 [微服务引擎MSE](https://www.aliyun.com/product/aliware/mse?spm=github.spring.com.topbar) 还提供了企业级微服务治理中心，包括全链路灰度、服务预热、无损上下线和离群实例摘除等更多更强大的治理能力，同时还提供了企业级 Nacos 注册配置中心，企业级云原生网关等多种产品及解决方案。\n\n## 组件\n\n**[Sentinel](https://github.com/alibaba/Sentinel)**：把流量作为切入点，从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。\n\n**[Nacos](https://github.com/alibaba/Nacos)**：一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。\n\n**[RocketMQ](https://rocketmq.apache.org/)**：一款开源的分布式消息系统，基于高可用分布式集群技术，提供低延时的、高可靠的消息发布与订阅服务。\n\n**[Seata](https://github.com/seata/seata)**：阿里巴巴开源产品，一个易于使用的高性能微服务分布式事务解决方案。\n\n**[Alibaba Cloud OSS](https://www.aliyun.com/product/oss)**: 阿里云对象存储服务（Object Storage Service，简称 OSS），是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。\n\n**[Alibaba Cloud SchedulerX](https://cn.aliyun.com/aliware/schedulerx)**: 阿里中间件团队开发的一款分布式任务调度产品，提供秒级、精准、高可靠、高可用的定时（基于 Cron 表达式）任务调度服务。\n\n**[Alibaba Cloud SMS](https://www.aliyun.com/product/sms)**: 覆盖全球的短信服务，友好、高效、智能的互联化通讯能力，帮助企业迅速搭建客户触达通道。\n\n更多组件请参考 [Roadmap](https://github.com/alibaba/spring-cloud-alibaba/blob/2025.1.x/Roadmap-zh.md)。\n\n## 如何构建\n* 2025.1.x 分支对应的是 Spring Cloud 2025.1.x 与 Spring Boot 4.0.x，最低支持 JDK 17。\n* 2025.0.x 分支对应的是 Spring Cloud 2025.0.x 与 Spring Boot 3.5.x，最低支持 JDK 17。\n* 2023.x 分支对应的是 Spring Cloud 2023 与 Spring Boot 3.2.x，最低支持 JDK 17。\n* 2022.x 分支对应的是 Spring Cloud 2022 与 Spring Boot 3.0.x，最低支持 JDK 17。\n* 2021.x 分支对应的是 Spring Cloud 2021 与 Spring Boot 2.6.x，最低支持 JDK 1.8。\n* 2020.0 分支对应的是 Spring Cloud 2020 与 Spring Boot 2.4.x，最低支持 JDK 1.8。\n* 2.2.x 分支对应的是 Spring Cloud Hoxton 与 Spring Boot 2.2.x，最低支持 JDK 1.8。\n* greenwich 分支对应的是 Spring Cloud Greenwich 与 Spring Boot 2.1.x，最低支持 JDK 1.8。\n* finchley 分支对应的是 Spring Cloud Finchley 与 Spring Boot 2.0.x，最低支持 JDK 1.8。\n* 1.x 分支对应的是 Spring Cloud Edgware 与 Spring Boot 1.x，最低支持 JDK 1.7。\n\nSpring Cloud 使用 Maven 来构建，最快的使用方式是将本项目 clone 到本地，然后执行以下命令：\n```bash\n./mvnw install\n```\n执行完毕后，项目将被安装到本地 Maven 仓库。\n\n## 如何使用\n\n### 如何引入依赖\n\n#### 正式版\n\n如果需要使用已发布的`正式版本`，在 `dependencyManagement` 中添加如下配置。\n```xml\n<dependencyManagement>\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-alibaba-dependencies</artifactId>\n            <version>2025.1.0.0</version>\n            <type>pom</type>\n            <scope>import</scope>\n        </dependency>\n    </dependencies>\n</dependencyManagement>\n```\n然后在 `dependencies` 中添加自己所需使用的依赖即可使用。如果你想选择老版本，可以参考[版本说明](https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E)。\n\n#### 快照\n\n如果需要使用已发布的`快照版本`，在 `dependencyManagement` 中添加如下配置。\n```xml\n<dependencyManagement>\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-alibaba-dependencies</artifactId>\n            <version>2025.1.0.0-SNAPSHOT</version>\n            <type>pom</type>\n            <scope>import</scope>\n        </dependency>\n    </dependencies>\n</dependencyManagement>\n```\n\n在 `repositories` 中添加如下配置。\n\n```xml\n<repositories>\n    <repository>\n        <id>github</id>\n        <url>https://maven.pkg.github.com/alibaba/spring-cloud-alibaba</url>\n        <releases>\n            <enabled>false</enabled>\n        </releases>\n        <snapshots>\n            <enabled>true</enabled>\n        </snapshots>\n    </repository>\n</repositories>\n```\n\n在 `settings.xml` 中添加如下配置。\n\n```xml\n<servers>\n    <server>\n        <id>github</id>\n        <username>你的 GitHub 用户名</username>\n        <password>你的 GitHub Token（需要 read:packages 权限）</password>\n    </server>\n</servers>\n```\n\n## 演示 Demo\n\n为了演示如何使用，Spring Cloud Alibaba 项目包含了一个子模块`spring-cloud-alibaba-examples`。此模块中提供了演示用的 example ，您可以阅读对应的 example 工程下的 readme 文档，根据里面的步骤来体验。\n\nExample 列表：\n\n[Sentinel Example](https://github.com/alibaba/spring-cloud-alibaba/tree/2025.1.x/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md)\n\n[Nacos Example](https://github.com/alibaba/spring-cloud-alibaba/blob/2025.1.x/spring-cloud-alibaba-examples/nacos-example/readme-zh.md)\n\n[RocketMQ Example](https://github.com/alibaba/spring-cloud-alibaba/blob/2025.1.x/spring-cloud-alibaba-examples/rocketmq-example/readme-zh.md)\n\n[Seata Example](https://github.com/alibaba/spring-cloud-alibaba/blob/2025.1.x/spring-cloud-alibaba-examples/seata-example/readme-zh.md)\n\n[Alibaba Cloud OSS Example](https://github.com/alibaba/aliyun-spring-boot/tree/master/aliyun-spring-boot-samples/aliyun-oss-spring-boot-sample)\n\n[Alibaba Cloud SMS Example](https://github.com/alibaba/aliyun-spring-boot/tree/master/aliyun-spring-boot-samples/aliyun-sms-spring-boot-sample)\n\n[Alibaba Cloud SchedulerX Example](https://github.com/alibaba/aliyun-spring-boot)\n\n## 版本管理规范\n\n项目的版本号格式为 x.x.x 的形式，其中 x 的数值类型为数字，从 0 开始取值，且不限于 0~9 这个范围。项目处于孵化器阶段时，第一位版本号固定使用 0，即版本号为 0.x.x 的格式。\n\n由于 Spring Boot 1 和 Spring Boot 2 在 Actuator 模块的接口和注解有很大的变更，且 spring-cloud-commons 从 1.x.x 版本升级到 2.0.0 版本也有较大的变更，因此我们采取跟 SpringBoot 版本号一致的版本:\n\n* 1.5.x 版本适用于 Spring Boot 1.5.x\n* 2.0.x 版本适用于 Spring Boot 2.0.x\n* 2.1.x 版本适用于 Spring Boot 2.1.x\n* 2.2.x 版本适用于 Spring Boot 2.2.x\n* 2020.x 版本适用于 Spring Boot 2.4.x\n* 2021.x 版本适用于 Spring Boot 2.6.x\n* 2022.x 版本适用于 Spring Boot 3.0.x\n* 2023.x 版本适用于 Spring Boot 3.2.x\n* 2025.0.x 版本适用于 Spring Boot 3.5.x\n* 2025.1.x 版本适用于 Spring Boot 4.0.x\n\n## 社区交流\n\n### 邮件列表\n\nspring-cloud-alibaba@googlegroups.com，欢迎通过此邮件列表讨论与 spring-cloud-alibaba 相关的一切。\n\n### 钉钉群\n\n* Spring Cloud Alibaba 开源交流群（1群）：21914947\n* Spring Cloud Alibaba 开源交流群（2群，已满）：21992595\n* Spring Cloud Alibaba 开源交流群（3群，已满）：35153903\n* Spring Cloud Alibaba 开源交流群（4群，已满）：30301472\n* Spring Cloud Alibaba 开源交流群（5群，已满）：34930571\n* Spring Cloud Alibaba 开源交流群（6群，已满）：34351718\n* Spring Cloud Alibaba 开源交流群（7群）：2415000986\n\n## 社区相关开源\n\n**[Nepxion Discovery](https://github.com/Nepxion/Discovery)**：一款集成Spring Cloud Alibaba、Nacos、Sentinel等阿里巴巴中间件，实现网关和服务的灰度发布、路由、权重、限流、熔断、降级、隔离、监控、追踪等功能的微服务开源解决。使用指南 请参考 **[Nepxion Discovery Guide](https://github.com/Nepxion/DiscoveryGuide)**。\n"
  },
  {
    "path": "README.md",
    "content": "# Spring Cloud Alibaba\n\n[![CircleCI](https://circleci.com/gh/alibaba/spring-cloud-alibaba/tree/2025.1.x.svg?style=svg)](https://circleci.com/gh/alibaba/spring-cloud-alibaba/tree/2025.1.x)\n[![Maven Central](https://img.shields.io/maven-central/v/com.alibaba.cloud/spring-cloud-alibaba-dependencies.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:com.alibaba.cloud%20AND%20a:spring-cloud-alibaba-dependencies)\n[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)\n[![actions](https://github.com/alibaba/spring-cloud-alibaba/workflows/Integration%20Testing/badge.svg)](https://github.com/alibaba/spring-cloud-alibaba/actions)\n[![Leaderboard](https://img.shields.io/badge/SCA-Check%20Your%20Contribution-orange)](https://opensource.alibaba.com/contribution_leaderboard/details?projectValue=sca)\n\nA project maintained by Alibaba.\n\nSee the [中文文档](https://github.com/alibaba/spring-cloud-alibaba/blob/2025.1.x/README-zh.md) for Chinese readme.\n\nSpring Cloud Alibaba provides a one-stop solution for distributed application development. It contains all the components required to develop distributed applications, making it easy for you to develop your applications using Spring Cloud.\n\nWith Spring Cloud Alibaba, you only need to add some annotations and a small amount of configurations to connect Spring Cloud applications to the distributed solutions of Alibaba, and build a distributed application system with Alibaba middleware.\n\n\n## Features\n\n* **Flow control and service degradation**: Flow control for HTTP services is supported by default. You can also customize flow control and service degradation rules using annotations. The rules can be changed dynamically.\n* **Service registration and discovery**: Service can be registered and clients can discover the instances using Spring-managed beans. Load balancing is consistent with that supported by the corresponding Spring Cloud.\n* **Distributed configuration**: Support for externalized configuration in a distributed system, auto refresh when configuration changes.\n* **Event-driven**: Support for building highly scalable event-driven microservices connected with shared messaging systems.\n* **Distributed Transaction**: Support for distributed transaction solution with high performance and ease of use.\n* **Alibaba Cloud Object Storage**: Massive, secure, low-cost, and highly reliable cloud storage services. Support for storing and accessing any type of data in any application, anytime, anywhere.\n* **Alibaba Cloud SchedulerX**: Accurate, highly reliable, and highly available scheduled job scheduling services with response time within seconds.\n* **Alibaba Cloud SMS**: A messaging service that covers the globe, Alibaba SMS provides convenient, efficient, and intelligent communication capabilities that help businesses quickly contact their customers.\n\nFor more features, please refer to [Roadmap](https://github.com/alibaba/spring-cloud-alibaba/blob/2025.1.x/Roadmap.md).\n\nIn addition to the above-mentioned features, for the needs of enterprise users' scenarios, [Microservices Engine (MSE)](https://www.aliyun.com/product/aliware/mse?spm=github.spring.com.topbar) of Spring Cloud Alibaba's enterprise version provides an enterprise-level microservices governance center, which includes more powerful governance capabilities such as Grayscale Release, Service Warm-up, Lossless Online and Offline and Outlier Ejection. At the same time, it also provides a variety of products and solutions such as enterprise-level Nacos registration / configuration center, enterprise-level cloud native gateway.\n\n\n## Components\n\n**[Sentinel](https://github.com/alibaba/Sentinel)**: Sentinel takes \"traffic flow\" as the breakthrough point, and provides solutions in areas such as flow control, concurrency, circuit breaking, and load protection to protect service stability.\n\n**[Nacos](https://github.com/alibaba/Nacos)**: An easy-to-use dynamic service discovery, configuration and service management platform for building cloud native applications.\n\n**[RocketMQ](https://rocketmq.apache.org/)**: A distributed messaging and streaming platform with low latency, high performance and reliability, trillion-level capacity and flexible scalability.\n\n**[Seata](https://github.com/seata/seata)**: A distributed transaction solution with high performance and ease of use for microservices architecture.\n\n**[Alibaba Cloud OSS](https://www.aliyun.com/product/oss)**: An encrypted and secure cloud storage service which stores, processes and accesses massive amounts of data from anywhere in the world.\n\n**[Alibaba Cloud SMS](https://www.aliyun.com/product/sms)**: A messaging service that covers the globe, Alibaba SMS provides convenient, efficient, and intelligent communication capabilities that help businesses quickly contact their customers.\n\n**[Alibaba Cloud SchedulerX](https://www.aliyun.com/aliware/schedulerx?spm=5176.10695662.784137.1.4b07363dej23L3)**: Accurate, highly reliable, and highly available scheduled job scheduling services with response time within seconds.\n\nFor more features please refer to [Roadmap](https://github.com/alibaba/spring-cloud-alibaba/blob/2025.1.x/Roadmap.md).\n\n## How to build\n* **2025.1.x branch**: Corresponds to Spring Cloud 2025.1.x & Spring Boot 4.0.x, JDK 17 or later versions are supported.\n* **2025.0.x branch**: Corresponds to Spring Cloud 2025.0.x & Spring Boot 3.5.x, JDK 17 or later versions are supported.\n* **2023.x branch**: Corresponds to Spring Cloud 2023 & Spring Boot 3.2.x, JDK 17 or later versions are supported.\n* **2022.x branch**: Corresponds to Spring Cloud 2022 & Spring Boot 3.0.x, JDK 17 or later versions are supported.\n* **2021.x branch**: Corresponds to Spring Cloud 2021 & Spring Boot 2.6.x. JDK 1.8 or later versions are supported.\n* **2020.0 branch**: Corresponds to Spring Cloud 2020 & Spring Boot 2.4.x. JDK 1.8 or later versions are supported.\n* **2.2.x branch**: Corresponds to Spring Cloud Hoxton & Spring Boot 2.2.x. JDK 1.8 or later versions are supported.\n* **greenwich branch**: Corresponds to Spring Cloud Greenwich & Spring Boot 2.1.x. JDK 1.8 or later versions are supported.\n* **finchley branch**: Corresponds to Spring Cloud Finchley & Spring Boot 2.0.x. JDK 1.8 or later versions are supported.\n* **1.x branch**: Corresponds to Spring Cloud Edgware & Spring Boot 1.x, JDK 1.7 or later versions are supported.\n\nSpring Cloud uses Maven for most build-related activities, and you should be able to get off the ground quite quickly by cloning the project you are interested in and typing:\n```bash\n./mvnw install\n```\n\n## How to Use\n\n### Add maven dependency \n\n#### Release Version\n\nThese artifacts are available from Maven Central and Spring Release repository via BOM:\n```xml\n<dependencyManagement>\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-alibaba-dependencies</artifactId>\n            <version>2025.1.0.0</version>\n            <type>pom</type>\n            <scope>import</scope>\n        </dependency>\n    </dependencies>\n</dependencyManagement>\n```\nadd the module in  `dependencies`. If you want to choose an older version, you can refer to the [Release Notes](https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E).\n\n#### Snapshot\n\nIf you need to use the already published `Snapshot Version`, add the following configuration in the `dependencyManagement`.\n```xml\n<dependencyManagement>\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-alibaba-dependencies</artifactId>\n            <version>2025.1.0.0-SNAPSHOT</version>\n            <type>pom</type>\n            <scope>import</scope>\n        </dependency>\n    </dependencies>\n</dependencyManagement>\n```\n\nAdd the following configuration in `repositories`.\n```xml\n<repositories>\n    <repository>\n        <id>github</id>\n        <url>https://maven.pkg.github.com/alibaba/spring-cloud-alibaba</url>\n        <releases>\n            <enabled>false</enabled>\n        </releases>\n        <snapshots>\n            <enabled>true</enabled>\n        </snapshots>\n    </repository>\n</repositories>\n```\n\nAdd the following configuration in `settings.xml`.\n```xml\n<servers>\n    <server>\n        <id>github</id>\n        <username>Your GitHub Username</username>\n        <password>Your GitHub Token (requires read:packages permission)</password>\n    </server>\n</servers>\n```\n\n## Examples\n\nA `spring-cloud-alibaba-examples` module is included in our project for you to get started with Spring Cloud Alibaba quickly. It contains an example, and you can refer to the readme file in the example project for a quick walkthrough.\n\nExamples：\n\n[Sentinel Example](https://github.com/alibaba/spring-cloud-alibaba/tree/2025.1.x/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md)\n\n[Nacos Example](https://github.com/alibaba/spring-cloud-alibaba/blob/2025.1.x/spring-cloud-alibaba-examples/nacos-example/readme.md)\n\n[RocketMQ Example](https://github.com/alibaba/spring-cloud-alibaba/blob/2025.1.x/spring-cloud-alibaba-examples/rocketmq-example/readme.md)\n\n[Alibaba Cloud OSS Example](https://github.com/alibaba/aliyun-spring-boot/tree/master/aliyun-spring-boot-samples/aliyun-oss-spring-boot-sample)\n\n## Version control guidelines\nThe version number of the project is in the form of x.x.x, where x is a number, starting from 0, and is not limited to the range 0~9. When the project is in the incubator phase, the version number is 0.x.x.\n\nAs the interfaces and annotations of Spring Boot 1 and Spring Boot 2 have been changed significantly in the Actuator module, and spring-cloud-commons is also changed quite a lot from 1.x.x to 2.0.0, we take the same version rule as SpringBoot version number.\n\n* 1.5.x for Spring Boot 1.5.x\n* 2.0.x for Spring Boot 2.0.x\n* 2.1.x for Spring Boot 2.1.x\n* 2.2.x for Spring Boot 2.2.x\n* 2020.x for Spring Boot 2.4.x\n* 2021.x for Spring Boot 2.6.x\n* 2022.x for Spring Boot 3.0.x\n* 2023.x for Spring Boot 3.2.x\n* 2025.0.x for Spring Boot 3.5.x\n* 2025.1.x for Spring Boot 4.0.x\n\n## Code of Conduct\nThis project is a sub-project of Spring Cloud, it adheres to the Contributor Covenant [code of conduct](https://sca.aliyun.com/en-us/community/developer/contributor-guide/new-contributor-guide_dev/). By participating, you are expected to uphold this code. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.\n\n## Code Conventions and Housekeeping\nNone of these is essential for a pull request, but they will all help. They can also be added after the original pull request but before a merge.\n\nUse the Spring Framework code format conventions. If you use Eclipse you can import formatter settings using the eclipse-code-formatter.xml file from the Spring Cloud Build project. If using IntelliJ, you can use the Eclipse Code Formatter Plugin to import the same file.\n\nMake sure all new .java files to have a simple Javadoc class comment with at least an @author tag identifying you, and preferably at least a paragraph on what the class is for.\n\nAdd the ASF license header comment to all new .java files (copy from existing files in the project)\n\nAdd yourself as an @author to the .java files that you modify substantially (more than cosmetic changes).\n\nAdd some Javadocs and, if you change the namespace, some XSD doc elements.\n\nA few unit tests would help a lot as well —— someone has to do it.\n\nIf no-one else is using your branch, please rebase it against the current 2023.x (or other target branch in the main project).\n\nWhen writing a commit message please follow these conventions, if you are fixing an existing issue please add Fixes gh-XXXX at the end of the commit message (where XXXX is the issue number).\n\n## Contact Us\nMailing list is recommended for discussing almost anything related to spring-cloud-alibaba. \n\nspring-cloud-alibaba@googlegroups.com: You can ask questions here if you encounter any problem when using or developing spring-cloud-alibaba.\n"
  },
  {
    "path": "Roadmap-zh.md",
    "content": "# Roadmap\n\n[Spring Cloud Alibaba](https://github.com/alibaba/spring-cloud-alibaba) 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用服务的必需组件，方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。\n\n此项目包含的组件内容，主要选取自阿里巴巴开源中间件，但也不限定于这些产品。\n\n如果您对 Roadmap 有任何建议或想法，欢迎在 issues 中或者通过其他社区渠道向我们提出，一起讨论。\n\n- Github Issue：https://github.com/alibaba/spring-cloud-alibaba/issues\n- 钉钉交流群：“群8 Spring Cloud Alibaba交流群”群的钉钉群号： 33610001098\n\n\n## 已包含的组件\n\n**Sentinel**\n\n阿里巴巴开源产品，把流量作为切入点，从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。\n\n**Nacos**\n\n阿里巴巴开源产品，一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。\n\n**RocketMQ**\n\nApache RocketMQ™ 一款开源的分布式消息系统，基于高可用分布式集群技术，提供低延时的、高可靠的消息发布与订阅服务。\n\n**Seata**\n\n阿里巴巴开源产品（现捐赠给 Apache 基金会），一款开源的分布式事务解决方案，致力于在微服务架构下提供高性能和简单易用的分布式事务服务。\n\n## 未来发展方向\n\n## Spring Cloud Admin 服务治理（可观测方向）\n\nSpring Cloud Admin 定位为一款可视化的微服务管控平台，通过它能够查看整个 Spring Cloud 微服务状态（包括服务数、实例数、应用数等）。同时 Spring Cloud Admin 还应与主流的 [Apache SkyWalking](https://skywalking.apache.org/)，[OpenTelemetry](https://opentelemetry.io/) 等可观测性系统集成，提供对集群状态的指标查询与监控能力。\n\n## Spring Cloud Alibaba AI\n\n随着 LLM 的爆火，各种 AI 应用开发框架应运而生。其中包括 LangChain，LangChain4J，Spring AI 等项目，为 AI 应用开发提供了一系列的解决方案。\n\n本项目是基于 Spring AI 提供对阿里通义系列大模型的完整支持，包括对话，文生图，文生语音，语音转录等功能。旨在为开发微服务 AI 应用提供便利，屏蔽底层复杂性，使得 AI 可以快速接入 Spring Cloud 微服务体系。\n\n## Proxyless Mesh\n\nSpring Cloud Alibaba 也积极在 Proxyless 方向上探索，目前已经完成了 Routing，Xds-adapter 等功能。未来会推出更多云原生场景下的 Proxyless 功能特性。\n\n## RPC 方向上的探索\n\nSpring Cloud Alibaba RPC 组件主要依赖于 OpenFeign，RestTemplate 等。社区计划通过加入 GRPC，Dubbo 的 rpc 解决方案，进一步增强社区的 RPC 组件能力。\n\n## 分布式任务调度\n\nSpring Cloud Alibaba 缺少对分布式调度任务的支持，社区计划通过适配开源的分布式任务调度框架，来完善这部分能力。\n"
  },
  {
    "path": "Roadmap.md",
    "content": "# Roadmap\n\nSee the [中文文档](https://github.com/alibaba/spring-cloud-alibaba/blob/2025.1.x/Roadmap-zh.md) for Chinese Roadmap.\n\n\nSpring Cloud Alibaba provides a one-stop solution for microservices development. It contains all the components required to develop distributed applications, making it easy for you to develop your applications through the Spring Cloud programming model.\n\nThis project contains components from both open-source and commercialized Alibaba middleware products，but are not limited to them.\n\nIf you have any suggestions on our roadmap, feel free to submit issues or contact us via the other channels.\n\n- Github Issue：https://github.com/alibaba/spring-cloud-alibaba/issues\n- DingTalk communication group: \"Group 8 Spring Cloud Alibaba communication group\" DingTalk group number: 33610001098\n\n\n## Components\n\n**Sentinel**\n\nAn open-source project of Alibaba, Sentinel takes \"flow\" as breakthrough point, and provides solutions in areas such as flow control, concurrency, circuit breaking, and load protection to protect service stability.\n\n**Nacos**\n\nAn opensource project of Alibaba, an easy-to-use dynamic service discovery, configuration and service management platform for building cloud native applications.\n\n**RocketMQ**\n\nApache RocketMQ™ is an open source distributed messaging system based on highly available distributed cluster technology, providing low latency, highly reliable message publishing and subscription services.\n\n**Seata**\n\nAn opensource project of Alibaba(now donated to the Apache Foundation), a distributed transaction solution dedicated to providing high-performance and easy-to-use distributed transaction services under a microservice architecture.\n\n\n## Future Development Direction\n\n## Spring Cloud Admin Service Governance (Observable Direction)\n\nSpring Cloud Admin is positioned as a visual microservice management and control platform, through which you can view the status of the entire Spring Cloud microservice (including the number of services, the number of instances, the number of applications, etc.). At the same time, Spring Cloud Admin should also be integrated with mainstream observability systems such as [Apache SkyWalking](https://skywalking.apache.org/) and [OpenTelemetry](https://opentelemetry.io/) to provide indicator query and monitoring capabilities for cluster status.\n\n## Spring Cloud Alibaba AI\n\nWith the explosion of LLM, various AI application development frameworks have emerged as the times require. These include LangChain, LangChain4J, Spring AI and other projects, providing a series of solutions for AI application development.\n\nThis project is based on Spring AI to provide complete support for Ali Tongyi series large models, providing for chat, text-to-image, audiotranscription and other functions. It aims to facilitate the development of microservice AI applications, shield the underlying complexity, and enable AI to quickly access the Spring Cloud microservice system.\n\n## Proxyless Mesh\n\nSpring Cloud Alibaba is also actively exploring in the direction of Proxyless, and has completed functions such as Routing and Xds-adapter. In the future, more Proxyless features in cloud-native scenarios will be launched.\n\n## Exploration in the direction of RPC\n\nSpring Cloud Alibaba RPC components mainly rely on OpenFeign, RestTemplate, etc. The community plans to further enhance the community's RPC component capabilities by joining GRPC, Dubbo's RPC solution.\n\n## Distributed task scheduling\n\nSpring Cloud Alibaba lacks support for distributed scheduling tasks, the community plans to improve this part of the ability by adapting open source distributed task scheduling framework.\n"
  },
  {
    "path": "eclipse/checkstyle-suppressions.xml",
    "content": "<?xml version=\"1.0\"?>\n<!DOCTYPE suppressions PUBLIC\n        \"-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN\"\n        \"https://checkstyle.org/dtds/suppressions_1_2.dtd\">\n<suppressions>\n    <suppress files=\"[\\\\/]spring-cloud-alibaba-examples[\\\\/]\" checks=\"HideUtilityClassConstructorCheck\" />\n    <suppress files=\"[\\\\/]spring-cloud-alibaba-tests[\\\\/]\" checks=\"HideUtilityClassConstructorCheck\" />\n    <suppress files=\".*\" checks=\"LineLength\" />\n</suppressions>"
  },
  {
    "path": "eclipse/eclipse-code-formatter.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<profiles version=\"12\">\n<profile kind=\"CodeFormatterProfile\" name=\"Spring Boot Java Conventions\" version=\"12\">\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_ellipsis\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_after_imports\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.format_javadoc_comments\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indentation.size\" value=\"8\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.disabling_tag\" value=\"@formatter:off\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.continuation_indentation\" value=\"2\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_enum_constants\" value=\"0\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_before_imports\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_after_package\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_binary_operator\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.indent_root_tags\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.enabling_tag\" value=\"@formatter:on\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.compiler.problem.enumIdentifier\" value=\"error\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_statements_compare_to_block\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.line_length\" value=\"90\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.disabling_tag\" value=\"@formatter:off\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.use_on_off_tags\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_method_declaration\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body\" value=\"0\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_binary_expression\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_block\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_lambda_body\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.compact_else_if\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.compiler.problem.assertIdentifier\" value=\"error\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_binary_operator\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_unary_operator\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_ellipsis\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.format_line_comments\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.align_type_members_on_columns\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_assignment\" value=\"0\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration\" value=\"0\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_conditional_expression\" value=\"80\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_block_in_case\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.format_header\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode\" value=\"enabled\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_method_declaration\" value=\"0\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.join_wrapped_lines\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_resources_in_try\" value=\"80\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.compiler.source\" value=\"17\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.tabulation.size\" value=\"4\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.format_source_code\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_before_field\" value=\"0\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer\" value=\"2\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_before_method\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.compiler.codegen.targetPlatform\" value=\"17\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_switch\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.format_html\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_compact_if\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_empty_lines\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_unary_operator\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation\" value=\"0\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_after_label\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_before_member_type\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_semicolon\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.format_block_comments\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_statements_compare_to_body\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_multiple_fields\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_array_initializer\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.wrap_before_binary_operator\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.compiler.compliance\" value=\"17\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_enum_constant\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_type_declaration\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_before_package\" value=\"0\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.join_lines_in_comments\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.indent_parameter_description\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.tabulation.char\" value=\"tab\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_between_import_groups\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.lineSplit\" value=\"90\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch\" value=\"insert\"/>\n</profile>\n</profiles>\n"
  },
  {
    "path": "eclipse/org.eclipse.jdt.core.prefs",
    "content": "eclipse.preferences.version=1\norg.eclipse.jdt.core.codeComplete.argumentPrefixes=\norg.eclipse.jdt.core.codeComplete.argumentSuffixes=\norg.eclipse.jdt.core.codeComplete.fieldPrefixes=\norg.eclipse.jdt.core.codeComplete.fieldSuffixes=\norg.eclipse.jdt.core.codeComplete.localPrefixes=\norg.eclipse.jdt.core.codeComplete.localSuffixes=\norg.eclipse.jdt.core.codeComplete.staticFieldPrefixes=\norg.eclipse.jdt.core.codeComplete.staticFieldSuffixes=\norg.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=\norg.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=\norg.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\norg.eclipse.jdt.core.compiler.codegen.methodParameters=generate\norg.eclipse.jdt.core.compiler.codegen.targetPlatform=17\norg.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve\norg.eclipse.jdt.core.compiler.compliance=17\norg.eclipse.jdt.core.compiler.debug.lineNumber=generate\norg.eclipse.jdt.core.compiler.debug.localVariable=generate\norg.eclipse.jdt.core.compiler.debug.sourceFile=generate\norg.eclipse.jdt.core.compiler.doc.comment.support=enabled\norg.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning\norg.eclipse.jdt.core.compiler.problem.assertIdentifier=error\norg.eclipse.jdt.core.compiler.problem.autoboxing=ignore\norg.eclipse.jdt.core.compiler.problem.comparingIdentical=warning\norg.eclipse.jdt.core.compiler.problem.deadCode=warning\norg.eclipse.jdt.core.compiler.problem.deprecation=warning\norg.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled\norg.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled\norg.eclipse.jdt.core.compiler.problem.discouragedReference=warning\norg.eclipse.jdt.core.compiler.problem.emptyStatement=ignore\norg.eclipse.jdt.core.compiler.problem.enumIdentifier=error\norg.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore\norg.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled\norg.eclipse.jdt.core.compiler.problem.fieldHiding=ignore\norg.eclipse.jdt.core.compiler.problem.finalParameterBound=warning\norg.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning\norg.eclipse.jdt.core.compiler.problem.forbiddenReference=warning\norg.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning\norg.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled\norg.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning\norg.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore\norg.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore\norg.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning\norg.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled\norg.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled\norg.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled\norg.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=default\norg.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore\norg.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning\norg.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore\norg.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore\norg.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore\norg.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled\norg.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public\norg.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=all_standard_tags\norg.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning\norg.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled\norg.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled\norg.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=default\norg.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore\norg.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled\norg.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore\norg.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore\norg.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning\norg.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning\norg.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore\norg.eclipse.jdt.core.compiler.problem.nullReference=ignore\norg.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning\norg.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore\norg.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore\norg.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore\norg.eclipse.jdt.core.compiler.problem.rawTypeReference=warning\norg.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore\norg.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore\norg.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore\norg.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore\norg.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore\norg.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled\norg.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning\norg.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled\norg.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled\norg.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore\norg.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning\norg.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled\norg.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning\norg.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore\norg.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning\norg.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore\norg.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning\norg.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore\norg.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore\norg.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled\norg.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled\norg.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled\norg.eclipse.jdt.core.compiler.problem.unusedImport=warning\norg.eclipse.jdt.core.compiler.problem.unusedLabel=warning\norg.eclipse.jdt.core.compiler.problem.unusedLocal=warning\norg.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore\norg.eclipse.jdt.core.compiler.problem.unusedParameter=ignore\norg.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled\norg.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled\norg.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled\norg.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning\norg.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning\norg.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning\norg.eclipse.jdt.core.compiler.processAnnotations=disabled\norg.eclipse.jdt.core.compiler.source=17\norg.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647\norg.eclipse.jdt.core.formatter.align_type_members_on_columns=false\norg.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16\norg.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0\norg.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16\norg.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16\norg.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16\norg.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16\norg.eclipse.jdt.core.formatter.alignment_for_assignment=0\norg.eclipse.jdt.core.formatter.alignment_for_binary_expression=16\norg.eclipse.jdt.core.formatter.alignment_for_compact_if=16\norg.eclipse.jdt.core.formatter.alignment_for_conditional_expression=16\norg.eclipse.jdt.core.formatter.alignment_for_enum_constants=0\norg.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16\norg.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0\norg.eclipse.jdt.core.formatter.alignment_for_method_declaration=0\norg.eclipse.jdt.core.formatter.alignment_for_module_statements=16\norg.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16\norg.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0\norg.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16\norg.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16\norg.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80\norg.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16\norg.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16\norg.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16\norg.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16\norg.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16\norg.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16\norg.eclipse.jdt.core.formatter.alignment_for_type_arguments=0\norg.eclipse.jdt.core.formatter.alignment_for_type_parameters=0\norg.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16\norg.eclipse.jdt.core.formatter.blank_lines_after_imports=1\norg.eclipse.jdt.core.formatter.blank_lines_after_package=1\norg.eclipse.jdt.core.formatter.blank_lines_before_field=0\norg.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0\norg.eclipse.jdt.core.formatter.blank_lines_before_imports=1\norg.eclipse.jdt.core.formatter.blank_lines_before_member_type=1\norg.eclipse.jdt.core.formatter.blank_lines_before_method=1\norg.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1\norg.eclipse.jdt.core.formatter.blank_lines_before_package=0\norg.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1\norg.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1\norg.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line\norg.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line\norg.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line\norg.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line\norg.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line\norg.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line\norg.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line\norg.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line\norg.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line\norg.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line\norg.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line\norg.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line\norg.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false\norg.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false\norg.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=false\norg.eclipse.jdt.core.formatter.comment.format_block_comments=true\norg.eclipse.jdt.core.formatter.comment.format_header=false\norg.eclipse.jdt.core.formatter.comment.format_html=true\norg.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true\norg.eclipse.jdt.core.formatter.comment.format_line_comments=true\norg.eclipse.jdt.core.formatter.comment.format_source_code=false\norg.eclipse.jdt.core.formatter.comment.indent_parameter_description=true\norg.eclipse.jdt.core.formatter.comment.indent_root_tags=false\norg.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=do not insert\norg.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert\norg.eclipse.jdt.core.formatter.comment.line_length=90\norg.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true\norg.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true\norg.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false\norg.eclipse.jdt.core.formatter.compact_else_if=true\norg.eclipse.jdt.core.formatter.continuation_indentation=2\norg.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2\norg.eclipse.jdt.core.formatter.disabling_tag=@formatter\\:off\norg.eclipse.jdt.core.formatter.enabling_tag=@formatter\\:on\norg.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false\norg.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true\norg.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true\norg.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true\norg.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true\norg.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true\norg.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true\norg.eclipse.jdt.core.formatter.indent_empty_lines=false\norg.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true\norg.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true\norg.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true\norg.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false\norg.eclipse.jdt.core.formatter.indentation.size=4\norg.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert\norg.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert\norg.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert\norg.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert\norg.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert\norg.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert\norg.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert\norg.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert\norg.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert\norg.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert\norg.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert\norg.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert\norg.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert\norg.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert\norg.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert\norg.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=insert\norg.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert\norg.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert\norg.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert\norg.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert\norg.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert\norg.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert\norg.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert\norg.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert\norg.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert\norg.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert\norg.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert\norg.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert\norg.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert\norg.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert\norg.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert\norg.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert\norg.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert\norg.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert\norg.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert\norg.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert\norg.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert\norg.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert\norg.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert\norg.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert\norg.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert\norg.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert\norg.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert\norg.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert\norg.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert\norg.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert\norg.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert\norg.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert\norg.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert\norg.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert\norg.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert\norg.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert\norg.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert\norg.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert\norg.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert\norg.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert\norg.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert\norg.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert\norg.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert\norg.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert\norg.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert\norg.eclipse.jdt.core.formatter.join_lines_in_comments=true\norg.eclipse.jdt.core.formatter.join_wrapped_lines=true\norg.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false\norg.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false\norg.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false\norg.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false\norg.eclipse.jdt.core.formatter.lineSplit=90\norg.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false\norg.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false\norg.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0\norg.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1\norg.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines\norg.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines\norg.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines\norg.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines\norg.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines\norg.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines\norg.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines\norg.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines\norg.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines\norg.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines\norg.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true\norg.eclipse.jdt.core.formatter.tabulation.char=tab\norg.eclipse.jdt.core.formatter.tabulation.size=4\norg.eclipse.jdt.core.formatter.use_on_off_tags=true\norg.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false\norg.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false\norg.eclipse.jdt.core.formatter.wrap_before_binary_operator=true\norg.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true\norg.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true\norg.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true\norg.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter"
  },
  {
    "path": "eclipse/org.eclipse.jdt.ui.prefs",
    "content": "cleanup.add_default_serial_version_id=true\ncleanup.add_generated_serial_version_id=false\ncleanup.add_missing_annotations=true\ncleanup.add_missing_deprecated_annotations=true\ncleanup.add_missing_methods=false\ncleanup.add_missing_nls_tags=false\ncleanup.add_missing_override_annotations=true\ncleanup.add_missing_override_annotations_interface_methods=true\ncleanup.add_serial_version_id=false\ncleanup.always_use_blocks=true\ncleanup.always_use_parentheses_in_expressions=false\ncleanup.always_use_this_for_non_static_field_access=true\ncleanup.always_use_this_for_non_static_method_access=false\ncleanup.convert_functional_interfaces=false\ncleanup.convert_to_enhanced_for_loop=false\ncleanup.correct_indentation=false\ncleanup.format_source_code=true\ncleanup.format_source_code_changes_only=false\ncleanup.insert_inferred_type_arguments=false\ncleanup.make_local_variable_final=false\ncleanup.make_parameters_final=false\ncleanup.make_private_fields_final=false\ncleanup.make_type_abstract_if_missing_method=false\ncleanup.make_variable_declarations_final=false\ncleanup.never_use_blocks=false\ncleanup.never_use_parentheses_in_expressions=true\ncleanup.organize_imports=true\ncleanup.qualify_static_field_accesses_with_declaring_class=false\ncleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true\ncleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true\ncleanup.qualify_static_member_accesses_with_declaring_class=true\ncleanup.qualify_static_method_accesses_with_declaring_class=false\ncleanup.remove_private_constructors=true\ncleanup.remove_redundant_type_arguments=true\ncleanup.remove_trailing_whitespaces=true\ncleanup.remove_trailing_whitespaces_all=true\ncleanup.remove_trailing_whitespaces_ignore_empty=false\ncleanup.remove_unnecessary_casts=true\ncleanup.remove_unnecessary_nls_tags=false\ncleanup.remove_unused_imports=true\ncleanup.remove_unused_local_variables=false\ncleanup.remove_unused_private_fields=true\ncleanup.remove_unused_private_members=false\ncleanup.remove_unused_private_methods=true\ncleanup.remove_unused_private_types=true\ncleanup.sort_members=false\ncleanup.sort_members_all=false\ncleanup.use_anonymous_class_creation=false\ncleanup.use_blocks=true\ncleanup.use_blocks_only_for_return_and_throw=false\ncleanup.use_lambda=true\ncleanup.use_parentheses_in_expressions=false\ncleanup.use_this_for_non_static_field_access=false\ncleanup.use_this_for_non_static_field_access_only_if_necessary=false\ncleanup.use_this_for_non_static_method_access=false\ncleanup.use_this_for_non_static_method_access_only_if_necessary=true\ncleanup.use_type_arguments=false\ncleanup_profile=_Spring Cloud Cleanup Conventions\ncleanup_settings_version=2\neclipse.preferences.version=1\neditor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true\nformatter_profile=_Spring Cloud Java Conventions\nformatter_settings_version=13\norg.eclipse.jdt.ui.exception.name=e\norg.eclipse.jdt.ui.gettersetter.use.is=true\norg.eclipse.jdt.ui.ignorelowercasenames=true\norg.eclipse.jdt.ui.importorder=java;javax;;org.springframework;\\#;\norg.eclipse.jdt.ui.javadoc=true\norg.eclipse.jdt.ui.keywordthis=false\norg.eclipse.jdt.ui.ondemandthreshold=9999\norg.eclipse.jdt.ui.overrideannotation=true\norg.eclipse.jdt.ui.staticondemandthreshold=9999\norg.eclipse.jdt.ui.text.custom_code_templates=<?xml version\\=\"1.0\" encoding\\=\"UTF-8\" standalone\\=\"no\"?><templates><template autoinsert\\=\"true\" context\\=\"gettercomment_context\" deleted\\=\"false\" description\\=\"Comment for getter method\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.gettercomment\" name\\=\"gettercomment\">/**\\n * @return the ${bare_field_name}\\n */</template><template autoinsert\\=\"true\" context\\=\"settercomment_context\" deleted\\=\"false\" description\\=\"Comment for setter method\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.settercomment\" name\\=\"settercomment\">/**\\n * @param ${param} the ${bare_field_name} to set\\n */</template><template autoinsert\\=\"true\" context\\=\"constructorcomment_context\" deleted\\=\"false\" description\\=\"Comment for created constructors\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.constructorcomment\" name\\=\"constructorcomment\">/**\\n * ${tags}\\n */</template><template autoinsert\\=\"false\" context\\=\"filecomment_context\" deleted\\=\"false\" description\\=\"Comment for created Java files\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.filecomment\" name\\=\"filecomment\">/*\\n * Copyright 2013-2023 the original author or 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 *      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 */</template><template autoinsert\\=\"false\" context\\=\"typecomment_context\" deleted\\=\"false\" description\\=\"Comment for created types\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.typecomment\" name\\=\"typecomment\">/**\\n * @author ${user}\\n */</template><template autoinsert\\=\"true\" context\\=\"fieldcomment_context\" deleted\\=\"false\" description\\=\"Comment for fields\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.fieldcomment\" name\\=\"fieldcomment\">/**\\n * \\n */</template><template autoinsert\\=\"true\" context\\=\"methodcomment_context\" deleted\\=\"false\" description\\=\"Comment for non-overriding methods\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.methodcomment\" name\\=\"methodcomment\">/**\\n * ${tags}\\n */</template><template autoinsert\\=\"true\" context\\=\"overridecomment_context\" deleted\\=\"false\" description\\=\"Comment for overriding methods\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.overridecomment\" name\\=\"overridecomment\">/* (non-Javadoc)\\n * ${see_to_overridden}\\n */</template><template autoinsert\\=\"true\" context\\=\"delegatecomment_context\" deleted\\=\"false\" description\\=\"Comment for delegate methods\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.delegatecomment\" name\\=\"delegatecomment\">/**\\n * ${tags}\\n * ${see_to_target}\\n */</template><template autoinsert\\=\"false\" context\\=\"newtype_context\" deleted\\=\"false\" description\\=\"Newly created files\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.newtype\" name\\=\"newtype\">${filecomment}\\n\\n${package_declaration}\\n${typecomment}\\n${type_declaration}</template><template autoinsert\\=\"true\" context\\=\"classbody_context\" deleted\\=\"false\" description\\=\"Code in new class type bodies\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.classbody\" name\\=\"classbody\">\\n</template><template autoinsert\\=\"true\" context\\=\"interfacebody_context\" deleted\\=\"false\" description\\=\"Code in new interface type bodies\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.interfacebody\" name\\=\"interfacebody\">\\n</template><template autoinsert\\=\"true\" context\\=\"enumbody_context\" deleted\\=\"false\" description\\=\"Code in new enum type bodies\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.enumbody\" name\\=\"enumbody\">\\n</template><template autoinsert\\=\"true\" context\\=\"annotationbody_context\" deleted\\=\"false\" description\\=\"Code in new annotation type bodies\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.annotationbody\" name\\=\"annotationbody\">\\n</template><template autoinsert\\=\"false\" context\\=\"catchblock_context\" deleted\\=\"false\" description\\=\"Code in new catch blocks\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.catchblock\" name\\=\"catchblock\">// ${todo} Auto-generated catch block\\nthrow new UnsupportedOperationException(\"Auto-generated method stub\", ${exception_var});</template><template autoinsert\\=\"false\" context\\=\"methodbody_context\" deleted\\=\"false\" description\\=\"Code in created method stubs\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.methodbody\" name\\=\"methodbody\">// ${todo} Auto-generated method stub\\nthrow new UnsupportedOperationException(\"Auto-generated method stub\");</template><template autoinsert\\=\"true\" context\\=\"constructorbody_context\" deleted\\=\"false\" description\\=\"Code in created constructor stubs\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.constructorbody\" name\\=\"constructorbody\">${body_statement}\\n// ${todo} Auto-generated constructor stub</template><template autoinsert\\=\"true\" context\\=\"getterbody_context\" deleted\\=\"false\" description\\=\"Code in created getters\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.getterbody\" name\\=\"getterbody\">return ${field};</template><template autoinsert\\=\"true\" context\\=\"setterbody_context\" deleted\\=\"false\" description\\=\"Code in created setters\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.setterbody\" name\\=\"setterbody\">${field} \\= ${param};</template></templates>\nsp_cleanup.add_default_serial_version_id=true\nsp_cleanup.add_generated_serial_version_id=false\nsp_cleanup.add_missing_annotations=true\nsp_cleanup.add_missing_deprecated_annotations=true\nsp_cleanup.add_missing_methods=false\nsp_cleanup.add_missing_nls_tags=false\nsp_cleanup.add_missing_override_annotations=true\nsp_cleanup.add_missing_override_annotations_interface_methods=true\nsp_cleanup.add_serial_version_id=false\nsp_cleanup.always_use_blocks=true\nsp_cleanup.always_use_parentheses_in_expressions=true\nsp_cleanup.always_use_this_for_non_static_field_access=true\nsp_cleanup.always_use_this_for_non_static_method_access=false\nsp_cleanup.convert_to_enhanced_for_loop=false\nsp_cleanup.correct_indentation=false\nsp_cleanup.format_source_code=true\nsp_cleanup.format_source_code_changes_only=false\nsp_cleanup.make_local_variable_final=false\nsp_cleanup.make_parameters_final=false\nsp_cleanup.make_private_fields_final=false\nsp_cleanup.make_type_abstract_if_missing_method=false\nsp_cleanup.make_variable_declarations_final=false\nsp_cleanup.never_use_blocks=false\nsp_cleanup.never_use_parentheses_in_expressions=false\nsp_cleanup.on_save_use_additional_actions=true\nsp_cleanup.organize_imports=true\nsp_cleanup.qualify_static_field_accesses_with_declaring_class=false\nsp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true\nsp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true\nsp_cleanup.qualify_static_member_accesses_with_declaring_class=true\nsp_cleanup.qualify_static_method_accesses_with_declaring_class=false\nsp_cleanup.remove_private_constructors=true\nsp_cleanup.remove_trailing_whitespaces=true\nsp_cleanup.remove_trailing_whitespaces_all=true\nsp_cleanup.remove_trailing_whitespaces_ignore_empty=false\nsp_cleanup.remove_unnecessary_casts=true\nsp_cleanup.remove_unnecessary_nls_tags=false\nsp_cleanup.remove_unused_imports=true\nsp_cleanup.remove_unused_local_variables=false\nsp_cleanup.remove_unused_private_fields=true\nsp_cleanup.remove_unused_private_members=false\nsp_cleanup.remove_unused_private_methods=true\nsp_cleanup.remove_unused_private_types=true\nsp_cleanup.sort_members=false\nsp_cleanup.sort_members_all=false\nsp_cleanup.use_blocks=true\nsp_cleanup.use_blocks_only_for_return_and_throw=false\nsp_cleanup.use_parentheses_in_expressions=false\nsp_cleanup.use_this_for_non_static_field_access=true\nsp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false\nsp_cleanup.use_this_for_non_static_method_access=false\nsp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true"
  },
  {
    "path": "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#    https://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# Maven Start Up Batch script\n#\n# Required ENV vars:\n# ------------------\n#   JAVA_HOME - location of a JDK home dir\n#\n# Optional ENV vars\n# -----------------\n#   M2_HOME - location of maven2's installed home dir\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\n  CYGWIN*) cygwin=true ;;\n  MINGW*) mingw=true;;\n  Darwin*) 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        export JAVA_HOME=\"`/usr/libexec/java_home`\"\n      else\n        export JAVA_HOME=\"/Library/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\nif [ -z \"$M2_HOME\" ] ; then\n  ## resolve links - $0 may be a link to maven's home\n  PRG=\"$0\"\n\n  # need this for relative symlinks\n  while [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n      PRG=\"$link\"\n    else\n      PRG=\"`dirname \"$PRG\"`/$link\"\n    fi\n  done\n\n  saveddir=`pwd`\n\n  M2_HOME=`dirname \"$PRG\"`/..\n\n  # make it fully qualified\n  M2_HOME=`cd \"$M2_HOME\" && pwd`\n\n  cd \"$saveddir\"\n  # echo Using m2 at $M2_HOME\nfi\n\n# For Cygwin, ensure paths are in UNIX format before anything is touched\nif $cygwin ; then\n  [ -n \"$M2_HOME\" ] &&\n    M2_HOME=`cygpath --unix \"$M2_HOME\"`\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 \"$M2_HOME\" ] &&\n    M2_HOME=\"`(cd \"$M2_HOME\"; pwd)`\"\n  [ -n \"$JAVA_HOME\" ] &&\n    JAVA_HOME=\"`(cd \"$JAVA_HOME\"; pwd)`\"\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=\"`\\\\unset -f command; \\\\command -v java`\"\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.\"\nfi\n\nCLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher\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\n  if [ -z \"$1\" ]\n  then\n    echo \"Path not specified to find_maven_basedir\"\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=`cd \"$wdir/..\"; pwd`\n    fi\n    # end of workaround\n  done\n  echo \"${basedir}\"\n}\n\n# concatenates all lines of a file\nconcat_lines() {\n  if [ -f \"$1\" ]; then\n    echo \"$(tr -s '\\n' ' ' < \"$1\")\"\n  fi\n}\n\nBASE_DIR=`find_maven_basedir \"$(pwd)\"`\nif [ -z \"$BASE_DIR\" ]; then\n  exit 1;\nfi\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##########################################################################################\nif [ -r \"$BASE_DIR/.mvn/wrapper/maven-wrapper.jar\" ]; then\n    if [ \"$MVNW_VERBOSE\" = true ]; then\n      echo \"Found .mvn/wrapper/maven-wrapper.jar\"\n    fi\nelse\n    if [ \"$MVNW_VERBOSE\" = true ]; then\n      echo \"Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ...\"\n    fi\n    if [ -n \"$MVNW_REPOURL\" ]; then\n      jarUrl=\"$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar\"\n    else\n      jarUrl=\"https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar\"\n    fi\n    while IFS=\"=\" read key value; do\n      case \"$key\" in (wrapperUrl) jarUrl=\"$value\"; break ;;\n      esac\n    done < \"$BASE_DIR/.mvn/wrapper/maven-wrapper.properties\"\n    if [ \"$MVNW_VERBOSE\" = true ]; then\n      echo \"Downloading from: $jarUrl\"\n    fi\n    wrapperJarPath=\"$BASE_DIR/.mvn/wrapper/maven-wrapper.jar\"\n    if $cygwin; then\n      wrapperJarPath=`cygpath --path --windows \"$wrapperJarPath\"`\n    fi\n\n    if command -v wget > /dev/null; then\n        if [ \"$MVNW_VERBOSE\" = true ]; then\n          echo \"Found wget ... using wget\"\n        fi\n        if [ -z \"$MVNW_USERNAME\" ] || [ -z \"$MVNW_PASSWORD\" ]; then\n            wget \"$jarUrl\" -O \"$wrapperJarPath\" || rm -f \"$wrapperJarPath\"\n        else\n            wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD \"$jarUrl\" -O \"$wrapperJarPath\" || rm -f \"$wrapperJarPath\"\n        fi\n    elif command -v curl > /dev/null; then\n        if [ \"$MVNW_VERBOSE\" = true ]; then\n          echo \"Found curl ... using curl\"\n        fi\n        if [ -z \"$MVNW_USERNAME\" ] || [ -z \"$MVNW_PASSWORD\" ]; then\n            curl -o \"$wrapperJarPath\" \"$jarUrl\" -f\n        else\n            curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o \"$wrapperJarPath\" \"$jarUrl\" -f\n        fi\n\n    else\n        if [ \"$MVNW_VERBOSE\" = true ]; then\n          echo \"Falling back to using Java to download\"\n        fi\n        javaClass=\"$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java\"\n        # For Cygwin, switch paths to Windows format before running javac\n        if $cygwin; then\n          javaClass=`cygpath --path --windows \"$javaClass\"`\n        fi\n        if [ -e \"$javaClass\" ]; then\n            if [ ! -e \"$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class\" ]; then\n                if [ \"$MVNW_VERBOSE\" = true ]; then\n                  echo \" - Compiling MavenWrapperDownloader.java ...\"\n                fi\n                # Compiling the Java class\n                (\"$JAVA_HOME/bin/javac\" \"$javaClass\")\n            fi\n            if [ -e \"$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class\" ]; then\n                # Running the downloader\n                if [ \"$MVNW_VERBOSE\" = true ]; then\n                  echo \" - Running MavenWrapperDownloader.java ...\"\n                fi\n                (\"$JAVA_HOME/bin/java\" -cp .mvn/wrapper MavenWrapperDownloader \"$MAVEN_PROJECTBASEDIR\")\n            fi\n        fi\n    fi\nfi\n##########################################################################################\n# End of extension\n##########################################################################################\n\nexport MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-\"$BASE_DIR\"}\nif [ \"$MVNW_VERBOSE\" = true ]; then\n  echo $MAVEN_PROJECTBASEDIR\nfi\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 \"$M2_HOME\" ] &&\n    M2_HOME=`cygpath --path --windows \"$M2_HOME\"`\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\nexec \"$JAVACMD\" \\\n  $MAVEN_OPTS \\\n  $MAVEN_DEBUG_OPTS \\\n  -classpath \"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar\" \\\n  \"-Dmaven.home=${M2_HOME}\" \\\n  \"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}\" \\\n  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG \"$@\"\n"
  },
  {
    "path": "mvnw.cmd",
    "content": "@REM ----------------------------------------------------------------------------\n@REM Licensed to the Apache Software Foundation (ASF) under one\n@REM or more contributor license agreements.  See the NOTICE file\n@REM distributed with this work for additional information\n@REM regarding copyright ownership.  The ASF licenses this file\n@REM to you under the Apache License, Version 2.0 (the\n@REM \"License\"); you may not use this file except in compliance\n@REM with the License.  You may obtain a copy of the License at\n@REM\n@REM    https://www.apache.org/licenses/LICENSE-2.0\n@REM\n@REM Unless required by applicable law or agreed to in writing,\n@REM software distributed under the License is distributed on an\n@REM \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n@REM KIND, either express or implied.  See the License for the\n@REM specific language governing permissions and limitations\n@REM under the License.\n@REM ----------------------------------------------------------------------------\n\n@REM ----------------------------------------------------------------------------\n@REM Maven Start Up Batch script\n@REM\n@REM Required ENV vars:\n@REM JAVA_HOME - location of a JDK home dir\n@REM\n@REM Optional ENV vars\n@REM M2_HOME - location of maven2's installed home dir\n@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands\n@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending\n@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven\n@REM     e.g. to debug Maven itself, use\n@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000\n@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files\n@REM ----------------------------------------------------------------------------\n\n@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'\n@echo off\n@REM set title of command window\ntitle %0\n@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'\n@if \"%MAVEN_BATCH_ECHO%\" == \"on\"  echo %MAVEN_BATCH_ECHO%\n\n@REM set %HOME% to equivalent of $HOME\nif \"%HOME%\" == \"\" (set \"HOME=%HOMEDRIVE%%HOMEPATH%\")\n\n@REM Execute a user defined script before this one\nif not \"%MAVEN_SKIP_RC%\" == \"\" goto skipRcPre\n@REM check for pre script, once with legacy .bat ending and once with .cmd ending\nif exist \"%USERPROFILE%\\mavenrc_pre.bat\" call \"%USERPROFILE%\\mavenrc_pre.bat\" %*\nif exist \"%USERPROFILE%\\mavenrc_pre.cmd\" call \"%USERPROFILE%\\mavenrc_pre.cmd\" %*\n:skipRcPre\n\n@setlocal\n\nset ERROR_CODE=0\n\n@REM To isolate internal variables from possible post scripts, we use another setlocal\n@setlocal\n\n@REM ==== START VALIDATION ====\nif not \"%JAVA_HOME%\" == \"\" goto OkJHome\n\necho.\necho Error: JAVA_HOME not found in your environment. >&2\necho Please set the JAVA_HOME variable in your environment to match the >&2\necho location of your Java installation. >&2\necho.\ngoto error\n\n:OkJHome\nif exist \"%JAVA_HOME%\\bin\\java.exe\" goto init\n\necho.\necho Error: JAVA_HOME is set to an invalid directory. >&2\necho JAVA_HOME = \"%JAVA_HOME%\" >&2\necho Please set the JAVA_HOME variable in your environment to match the >&2\necho location of your Java installation. >&2\necho.\ngoto error\n\n@REM ==== END VALIDATION ====\n\n:init\n\n@REM Find the project base dir, i.e. the directory that contains the folder \".mvn\".\n@REM Fallback to current working directory if not found.\n\nset MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%\nIF NOT \"%MAVEN_PROJECTBASEDIR%\"==\"\" goto endDetectBaseDir\n\nset EXEC_DIR=%CD%\nset WDIR=%EXEC_DIR%\n:findBaseDir\nIF EXIST \"%WDIR%\"\\.mvn goto baseDirFound\ncd ..\nIF \"%WDIR%\"==\"%CD%\" goto baseDirNotFound\nset WDIR=%CD%\ngoto findBaseDir\n\n:baseDirFound\nset MAVEN_PROJECTBASEDIR=%WDIR%\ncd \"%EXEC_DIR%\"\ngoto endDetectBaseDir\n\n:baseDirNotFound\nset MAVEN_PROJECTBASEDIR=%EXEC_DIR%\ncd \"%EXEC_DIR%\"\n\n:endDetectBaseDir\n\nIF NOT EXIST \"%MAVEN_PROJECTBASEDIR%\\.mvn\\jvm.config\" goto endReadAdditionalConfig\n\n@setlocal EnableExtensions EnableDelayedExpansion\nfor /F \"usebackq delims=\" %%a in (\"%MAVEN_PROJECTBASEDIR%\\.mvn\\jvm.config\") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a\n@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%\n\n:endReadAdditionalConfig\n\nSET MAVEN_JAVA_EXE=\"%JAVA_HOME%\\bin\\java.exe\"\nset WRAPPER_JAR=\"%MAVEN_PROJECTBASEDIR%\\.mvn\\wrapper\\maven-wrapper.jar\"\nset WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain\n\nset DOWNLOAD_URL=\"https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar\"\n\nFOR /F \"usebackq tokens=1,2 delims==\" %%A IN (\"%MAVEN_PROJECTBASEDIR%\\.mvn\\wrapper\\maven-wrapper.properties\") DO (\n    IF \"%%A\"==\"wrapperUrl\" SET DOWNLOAD_URL=%%B\n)\n\n@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central\n@REM This allows using the maven wrapper in projects that prohibit checking in binary data.\nif exist %WRAPPER_JAR% (\n    if \"%MVNW_VERBOSE%\" == \"true\" (\n        echo Found %WRAPPER_JAR%\n    )\n) else (\n    if not \"%MVNW_REPOURL%\" == \"\" (\n        SET DOWNLOAD_URL=\"%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar\"\n    )\n    if \"%MVNW_VERBOSE%\" == \"true\" (\n        echo Couldn't find %WRAPPER_JAR%, downloading it ...\n        echo Downloading from: %DOWNLOAD_URL%\n    )\n\n    powershell -Command \"&{\"^\n\t\t\"$webclient = new-object System.Net.WebClient;\"^\n\t\t\"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {\"^\n\t\t\"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');\"^\n\t\t\"}\"^\n\t\t\"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')\"^\n\t\t\"}\"\n    if \"%MVNW_VERBOSE%\" == \"true\" (\n        echo Finished downloading %WRAPPER_JAR%\n    )\n)\n@REM End of extension\n\n@REM Provide a \"standardized\" way to retrieve the CLI args that will\n@REM work with both Windows and non-Windows executions.\nset MAVEN_CMD_LINE_ARGS=%*\n\n%MAVEN_JAVA_EXE% ^\n  %JVM_CONFIG_MAVEN_PROPS% ^\n  %MAVEN_OPTS% ^\n  %MAVEN_DEBUG_OPTS% ^\n  -classpath %WRAPPER_JAR% ^\n  \"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%\" ^\n  %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*\nif ERRORLEVEL 1 goto error\ngoto end\n\n:error\nset ERROR_CODE=1\n\n:end\n@endlocal & set ERROR_CODE=%ERROR_CODE%\n\nif not \"%MAVEN_SKIP_RC%\"==\"\" goto skipRcPost\n@REM check for post script, once with legacy .bat ending and once with .cmd ending\nif exist \"%USERPROFILE%\\mavenrc_post.bat\" call \"%USERPROFILE%\\mavenrc_post.bat\"\nif exist \"%USERPROFILE%\\mavenrc_post.cmd\" call \"%USERPROFILE%\\mavenrc_post.cmd\"\n:skipRcPost\n\n@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'\nif \"%MAVEN_BATCH_PAUSE%\"==\"on\" pause\n\nif \"%MAVEN_TERMINATE_CMD%\"==\"on\" exit %ERROR_CODE%\n\ncmd /C exit /B %ERROR_CODE%\n"
  },
  {
    "path": "pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>org.springframework.cloud</groupId>\n        <artifactId>spring-cloud-build</artifactId>\n\t\t<version>5.0.0</version>\n        <relativePath/>\n    </parent>\n\n    <groupId>com.alibaba.cloud</groupId>\n    <artifactId>spring-cloud-alibaba</artifactId>\n    <version>${revision}</version>\n    <packaging>pom</packaging>\n    <name>Spring Cloud Alibaba</name>\n    <description>Spring Cloud Alibaba</description>\n    <url>https://github.com/alibaba/spring-cloud-alibaba</url>\n\n    <licenses>\n        <license>\n            <name>Apache License, Version 2.0</name>\n            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>\n            <distribution>repo</distribution>\n        </license>\n    </licenses>\n\n    <scm>\n        <url>https://github.com/alibaba/spring-cloud-alibaba</url>\n        <connection>\n            scm:git:git://github.com/alibaba/spring-cloud-alibaba.git\n        </connection>\n        <developerConnection>\n            scm:git:ssh://git@github.com/alibaba/spring-cloud-alibaba.git\n        </developerConnection>\n        <tag>HEAD</tag>\n    </scm>\n\n    <developers>\n        <developer>\n            <name>xiaojing</name>\n            <email>flystar32@163.com</email>\n        </developer>\n        <developer>\n            <name>Jim Fang</name>\n            <email>fangjian0423@gmail.com</email>\n            <organization>Alibaba</organization>\n            <url>https://github.com/fangjian0423</url>\n        </developer>\n        <developer>\n            <name>xiaolongzuo</name>\n            <email>150349407@qq.com</email>\n        </developer>\n        <developer>\n            <name>hengyunabc</name>\n            <email>hengyunabc@gmail.com</email>\n        </developer>\n        <developer>\n            <id>mercyblitz</id>\n            <name>Mercy Ma</name>\n            <email>mercyblitz@gmail.com</email>\n            <organization>Alibaba</organization>\n            <url>https://github.com/mercyblitz</url>\n        </developer>\n        <developer>\n            <name>yunzheng</name>\n            <email>yunzheng1228@gmail.com</email>\n        </developer>\n        <developer>\n            <id>theonefx</id>\n            <name>theonefx</name>\n            <email>chenxilzx1@gmail.com</email>\n            <organization>Alibaba</organization>\n            <url>https://github.com/theonefx</url>\n        </developer>\n    </developers>\n\n    <properties>\n        <!-- Project revision -->\n        <revision>2025.1.0.1-SNAPSHOT</revision>\n\n        <!-- Spring Cloud -->\n        <spring.cloud.version>2025.1.0</spring.cloud.version>\n\n        <!-- Spring Boot -->\n        <spring-boot.version>4.0.0</spring-boot.version>\n\n        <maven.compiler.source>17</maven.compiler.source>\n        <maven.compiler.target>17</maven.compiler.target>\n\n        <!-- Maven Plugin Versions -->\n        <maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version>\n        <maven-deploy-plugin.version>3.1.4</maven-deploy-plugin.version>\n        <!-- JUnit 5 requires Surefire version 2.22.0 or higher -->\n        <maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version>\n        <maven-source-plugin.version>3.2.1</maven-source-plugin.version>\n        <maven-javadoc-plugin.version>3.11.2</maven-javadoc-plugin.version>\n        <maven-gpg-plugin.version>3.2.7</maven-gpg-plugin.version>\n        <flatten-maven-plugin.version>1.7.0</flatten-maven-plugin.version>\n        <gmavenplus-plugin.version>4.4.1</gmavenplus-plugin.version>\n        <jacoco.version>0.8.13</jacoco.version>\n        <native-maven-plugin.version>0.10.6</native-maven-plugin.version>\n\n        <!-- Maven Central Portal -->\n        <central.publishing.maven.version>0.7.0</central.publishing.maven.version>\n    </properties>\n\n    <modules>\n        <module>spring-cloud-alibaba-dependencies</module>\n        <module>spring-cloud-alibaba-examples</module>\n        <module>spring-cloud-alibaba-starters</module>\n        <module>spring-cloud-alibaba-coverage</module>\n        <module>spring-cloud-alibaba-tests</module>\n    </modules>\n\n    <dependencyManagement>\n        <dependencies>\n\n            <!-- Spring Dependencies -->\n            <dependency>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-dependencies</artifactId>\n                <version>${spring-boot.version}</version>\n                <type>pom</type>\n                <scope>import</scope>\n            </dependency>\n\n            <dependency>\n                <groupId>org.springframework.cloud</groupId>\n                <artifactId>spring-cloud-dependencies</artifactId>\n                <version>${spring.cloud.version}</version>\n                <type>pom</type>\n                <scope>import</scope>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.cloud</groupId>\n                <artifactId>spring-cloud-alibaba-dependencies</artifactId>\n                <version>${project.version}</version>\n                <type>pom</type>\n                <scope>import</scope>\n            </dependency>\n\n        </dependencies>\n    </dependencyManagement>\n\n    <build>\n        <pluginManagement>\n            <plugins>\n                <plugin>\n                    <groupId>org.jacoco</groupId>\n                    <artifactId>jacoco-maven-plugin</artifactId>\n                    <version>${jacoco.version}</version>\n                </plugin>\n\n                <!-- disable auto format from parent -->\n                <plugin>\n                    <groupId>io.spring.javaformat</groupId>\n                    <artifactId>spring-javaformat-maven-plugin</artifactId>\n                    <version>${spring-javaformat.version}</version>\n                    <executions>\n                        <execution>\n                            <phase>validate</phase>\n                            <configuration>\n                                <skip>true</skip>\n                            </configuration>\n                        </execution>\n                    </executions>\n                </plugin>\n\n                <plugin>\n                    <groupId>org.sonatype.central</groupId>\n                    <artifactId>central-publishing-maven-plugin</artifactId>\n                    <version>${central.publishing.maven.version}</version>\n                </plugin>\n            </plugins>\n        </pluginManagement>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-eclipse-plugin</artifactId>\n                <configuration>\n                    <useProjectReferences>false</useProjectReferences>\n                    <additionalConfig>\n                        <file>\n                            <name>.settings/org.eclipse.jdt.ui.prefs</name>\n                            <location>\n                                ${maven.multiModuleProjectDirectory}/eclipse/org.eclipse.jdt.ui.prefs\n                            </location>\n                        </file>\n                        <file>\n                            <name>.settings/org.eclipse.jdt.core.prefs</name>\n                            <location>\n                                ${maven.multiModuleProjectDirectory}/eclipse/org.eclipse.jdt.core.prefs\n                            </location>\n                        </file>\n                    </additionalConfig>\n                </configuration>\n            </plugin>\n\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-checkstyle-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <id>checkstyle-validation</id>\n                        <phase>validate</phase>\n                        <goals>\n                            <goal>check</goal>\n                        </goals>\n                        <configuration>\n                            <!-- Checkstyle rules inherited from spring-cloud-build -->\n                            <suppressionsLocation>${maven.multiModuleProjectDirectory}/eclipse/checkstyle-suppressions.xml</suppressionsLocation>\n                            <includeTestSourceDirectory>true</includeTestSourceDirectory>\n                            <consoleOutput>true</consoleOutput>\n                            <failsOnError>true</failsOnError>\n                            <failOnViolation>true</failOnViolation>\n                            <violationSeverity>warning</violationSeverity>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-compiler-plugin</artifactId>\n                <version>${maven-compiler-plugin.version}</version>\n                <inherited>true</inherited>\n                <configuration>\n                    <source>${maven.compiler.source}</source>\n                    <target>${maven.compiler.target}</target>\n                </configuration>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-surefire-plugin</artifactId>\n                <version>${maven-surefire-plugin.version}</version>\n                <inherited>true</inherited>\n                <configuration>\n                    <forkCount>1</forkCount>\n                    <reuseForks>false</reuseForks>\n                </configuration>\n            </plugin>\n            <plugin>\n                <groupId>org.codehaus.mojo</groupId>\n                <artifactId>flatten-maven-plugin</artifactId>\n                <version>${flatten-maven-plugin.version}</version>\n                <configuration>\n                    <updatePomFile>true</updatePomFile>\n                    <flattenMode>resolveCiFriendliesOnly</flattenMode>\n                </configuration>\n                <executions>\n                    <execution>\n                        <id>flatten</id>\n                        <phase>process-resources</phase>\n                        <goals>\n                            <goal>flatten</goal>\n                        </goals>\n                    </execution>\n                    <execution>\n                        <id>flatten.clean</id>\n                        <phase>clean</phase>\n                        <goals>\n                            <goal>clean</goal>\n                        </goals>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n\n    <reporting>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-checkstyle-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </reporting>\n\n\t<!-- Override org.springframework.cloud:spring-cloud-build distributionManagement -->\n\t<distributionManagement>\n\t\t<snapshotRepository>\n\t\t\t<id>github</id>\n\t\t\t<url>https://maven.pkg.github.com/alibaba/spring-cloud-alibaba</url>\n\t\t</snapshotRepository>\n\t</distributionManagement>\n\n    <profiles>\n        <profile>\n            <id>release</id>\n            <build>\n                <plugins>\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-source-plugin</artifactId>\n                        <version>${maven-source-plugin.version}</version>\n                        <executions>\n                            <execution>\n                                <phase>package</phase>\n                                <goals>\n                                    <goal>jar-no-fork</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-javadoc-plugin</artifactId>\n                        <version>${maven-javadoc-plugin.version}</version>\n                        <configuration>\n                            <doclint>none</doclint>\n                            <source>${maven.compiler.source}</source>\n                        </configuration>\n                        <executions>\n                            <execution>\n                                <phase>package</phase>\n                                <goals>\n                                    <goal>jar</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-gpg-plugin</artifactId>\n                        <version>${maven-gpg-plugin.version}</version>\n                        <executions>\n                            <execution>\n                                <phase>verify</phase>\n                                <goals>\n                                    <goal>sign</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n\n                    <plugin>\n                        <groupId>org.sonatype.central</groupId>\n                        <artifactId>central-publishing-maven-plugin</artifactId>\n                        <extensions>true</extensions>\n                        <configuration>\n                            <publishingServerId>central</publishingServerId>\n                            <excludeArtifacts>\n                                <excludeArtifact>spring-cloud-alibaba-coverage</excludeArtifact>\n                                <excludeArtifact>sentinel-core-example</excludeArtifact>\n                                <excludeArtifact>sentinel-openfeign-example</excludeArtifact>\n                                <excludeArtifact>sentinel-resttemplate-example</excludeArtifact>\n                                <excludeArtifact>sentinel-circuitbreaker-example</excludeArtifact>\n                                <excludeArtifact>sentinel-webflux-example</excludeArtifact>\n                                <excludeArtifact>sentinel-spring-cloud-gateway-example</excludeArtifact>\n                                <excludeArtifact>nacos-discovery-example</excludeArtifact>\n                                <excludeArtifact>nacos-config-example</excludeArtifact>\n                                <excludeArtifact>nacos-gateway-example</excludeArtifact>\n                                <excludeArtifact>business-service</excludeArtifact>\n                                <excludeArtifact>order-service</excludeArtifact>\n                                <excludeArtifact>storage-service</excludeArtifact>\n                                <excludeArtifact>account-service</excludeArtifact>\n                                <excludeArtifact>spring-cloud-alibaba-examples</excludeArtifact>\n                                <excludeArtifact>rocketmq-comprehensive-example</excludeArtifact>\n                                <excludeArtifact>rocketmq-orderly-consume-example</excludeArtifact>\n                                <excludeArtifact>rocketmq-broadcast-producer-example</excludeArtifact>\n                                <excludeArtifact>rocketmq-broadcast-consumer1-example</excludeArtifact>\n                                <excludeArtifact>rocketmq-broadcast-consumer2-example</excludeArtifact>\n                                <excludeArtifact>rocketmq-delay-consume-example</excludeArtifact>\n                                <excludeArtifact>rocketmq-sql-consume-example</excludeArtifact>\n                                <excludeArtifact>rocketmq-example-common</excludeArtifact>\n                                <excludeArtifact>rocketmq-tx-example</excludeArtifact>\n                                <excludeArtifact>rocketmq-pollable-consume-example</excludeArtifact>\n                                <excludeArtifact>spring-cloud-bus-rocketmq-example</excludeArtifact>\n                                <excludeArtifact>spring-cloud-alibaba-sidecar-nacos-example</excludeArtifact>\n                                <excludeArtifact>spring-cloud-alibaba-sidecar-consul-example</excludeArtifact>\n                                <excludeArtifact>nacos-gateway-discovery-example</excludeArtifact>\n                                <excludeArtifact>nacos-discovery-provider-example</excludeArtifact>\n                                <excludeArtifact>nacos-discovery-consumer-sclb-example</excludeArtifact>\n                                <excludeArtifact>nacos-discovery-spring-cloud-config-client-example</excludeArtifact>\n                                <excludeArtifact>nacos-discovery-consumer-example</excludeArtifact>\n                                <excludeArtifact>nacos-reactivediscovery-consumer-example</excludeArtifact>\n                                <excludeArtifact>nacos-gateway-provider-example</excludeArtifact>\n                                <excludeArtifact>nacos-discovery-spring-cloud-config-server-example</excludeArtifact>\n                                <excludeArtifact>integrated-storage</excludeArtifact>\n                                <excludeArtifact>integrated-account</excludeArtifact>\n                                <excludeArtifact>integrated-order</excludeArtifact>\n                                <excludeArtifact>integrated-gateway</excludeArtifact>\n                                <excludeArtifact>integrated-praise-provider</excludeArtifact>\n                                <excludeArtifact>integrated-praise-consumer</excludeArtifact>\n                                <excludeArtifact>integrated-common</excludeArtifact>\n                                <excludeArtifact>integrated-frontend</excludeArtifact>\n                                <excludeArtifact>spring-cloud-scheduling-example</excludeArtifact>\n                                <excludeArtifact>spring-cloud-alibaba-test-support</excludeArtifact>\n                                <excludeArtifact>nacos-tests</excludeArtifact>\n                                <excludeArtifact>nacos-config-test</excludeArtifact>\n                                <excludeArtifact>nacos-discovery-test</excludeArtifact>\n                                <excludeArtifact>rocketmq-tests</excludeArtifact>\n                                <excludeArtifact>rocketmq-stream-test</excludeArtifact>\n                                <excludeArtifact>sentinel-tests</excludeArtifact>\n                                <excludeArtifact>sentinel-flowcontrol-test</excludeArtifact>\n                                <excludeArtifact>sentinel-degrade-test</excludeArtifact>\n                            </excludeArtifacts>\n                        </configuration>\n                    </plugin>\n                </plugins>\n            </build>\n        </profile>\n    </profiles>\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-coverage/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <artifactId>spring-cloud-alibaba-coverage</artifactId>\n    <name>Spring Cloud Alibaba Coverage</name>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>\n            <version>${revision}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>\n            <version>${revision}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-circuitbreaker-sentinel</artifactId>\n            <version>${revision}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>\n            <version>${revision}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n            <version>${revision}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>\n            <version>${revision}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n            <version>${revision}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-bus-rocketmq</artifactId>\n            <version>${revision}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>\n            <version>${revision}</version>\n        </dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.jacoco</groupId>\n                <artifactId>jacoco-maven-plugin</artifactId>\n                <version>${jacoco.version}</version>\n                <executions>\n                    <execution>\n                        <id>report-aggregate</id>\n                        <phase>test</phase>\n                        <goals>\n                            <goal>report-aggregate</goal>\n                        </goals>\n                        <configuration>\n                            <outputDirectory>${basedir}/../target/site/jacoco</outputDirectory>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-dependencies/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>org.springframework.cloud</groupId>\n        <artifactId>spring-cloud-dependencies-parent</artifactId>\n        <version>5.0.0</version>\n        <relativePath/>\n    </parent>\n\n    <groupId>com.alibaba.cloud</groupId>\n    <artifactId>spring-cloud-alibaba-dependencies</artifactId>\n    <version>${revision}</version>\n    <packaging>pom</packaging>\n    <name>Spring Cloud Alibaba Dependencies</name>\n    <description>Spring Cloud Alibaba Dependencies</description>\n\n    <properties>\n        <revision>2025.1.0.1-SNAPSHOT</revision>\n        <sentinel.version>1.8.9</sentinel.version>\n        <nacos.client.version>3.1.1</nacos.client.version>\n        <seata.version>2.6.0</seata.version>\n\n        <!-- Apache RocketMQ -->\n        <rocketmq.version>5.3.1</rocketmq.version>\n\n        <!-- scheduling -->\n        <shedlock.version>5.10.0</shedlock.version>\n        <schedulerx.worker.version>1.13.3</schedulerx.worker.version>\n\n        <maven.compiler.source>17</maven.compiler.source>\n        <maven.compiler.target>17</maven.compiler.target>\n\n        <!-- Maven Plugin Versions -->\n        <maven-source-plugin.version>3.2.1</maven-source-plugin.version>\n        <maven-javadoc-plugin.version>3.11.2</maven-javadoc-plugin.version>\n        <maven-gpg-plugin.version>3.2.7</maven-gpg-plugin.version>\n        <flatten-maven-plugin.version>1.7.0</flatten-maven-plugin.version>\n\n        <!-- Maven Central Portal -->\n        <central.publishing.maven.version>0.7.0</central.publishing.maven.version>\n\n        <druid.version>1.2.27</druid.version>\n        <mybatis.version>3.0.5</mybatis.version>\n        <log4j-core.version>2.25.1</log4j-core.version>\n        <slf4j-api.version>2.0.17</slf4j-api.version>\n        <fastjson.version>2.0.58</fastjson.version>\n        <log4j-slf4j2-impl.version>2.25.1</log4j-slf4j2-impl.version>\n        <guava.version>33.4.8-jre</guava.version>\n        <lombok.version>1.18.38</lombok.version>\n    </properties>\n\n    <dependencyManagement>\n        <dependencies>\n\n            <!--Nacos-->\n            <dependency>\n                <groupId>com.alibaba.nacos</groupId>\n                <artifactId>nacos-client</artifactId>\n                <version>${nacos.client.version}</version>\n            </dependency>\n\n            <!-- Sentinel -->\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-core</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-parameter-flow-control</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-datasource-extension</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-datasource-apollo</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-datasource-zookeeper</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-datasource-nacos</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-datasource-redis</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-datasource-consul</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-web-servlet</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-spring-cloud-gateway-v6x-adapter</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-transport-simple-http</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-annotation-aspectj</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-reactor-adapter</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-cluster-server-default</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-cluster-client-default</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-spring-webflux-adapter</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-api-gateway-adapter-common</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.csp</groupId>\n                <artifactId>sentinel-spring-webmvc-v6x-adapter</artifactId>\n                <version>${sentinel.version}</version>\n            </dependency>\n            <!--apache Seata-->\n            <dependency>\n                <groupId>org.apache.seata</groupId>\n                <artifactId>seata-spring-boot-starter</artifactId>\n                <version>${seata.version}</version>\n            </dependency>\n            <!--Alibaba RocketMQ-->\n            <dependency>\n                <groupId>org.apache.rocketmq</groupId>\n                <artifactId>rocketmq-client</artifactId>\n                <version>${rocketmq.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.apache.rocketmq</groupId>\n                <artifactId>rocketmq-acl</artifactId>\n                <version>${rocketmq.version}</version>\n            </dependency>\n\n            <!-- Alibaba scheduling -->\n            <dependency>\n                <groupId>net.javacrumbs.shedlock</groupId>\n                <artifactId>shedlock-spring</artifactId>\n                <version>${shedlock.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>net.javacrumbs.shedlock</groupId>\n                <artifactId>shedlock-provider-jdbc-template</artifactId>\n                <version>${shedlock.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.aliyun.schedulerx</groupId>\n                <artifactId>schedulerx2-worker</artifactId>\n                <version>${schedulerx.worker.version}</version>\n            </dependency>\n\n            <!-- Own dependencies  -->\n            <dependency>\n                <groupId>com.alibaba.cloud</groupId>\n                <artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>\n                <version>${revision}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.alibaba.cloud</groupId>\n                <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>\n                <version>${revision}</version>\n            </dependency>\n\n            <!-- Own dependencies - Starters -->\n            <dependency>\n                <groupId>com.alibaba.cloud</groupId>\n                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>\n                <version>${revision}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.cloud</groupId>\n                <artifactId>spring-cloud-circuitbreaker-sentinel</artifactId>\n                <version>${revision}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.cloud</groupId>\n                <artifactId>spring-cloud-starter-alibaba-seata</artifactId>\n                <version>${revision}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.cloud</groupId>\n                <artifactId>spring-alibaba-nacos-config</artifactId>\n                <version>${revision}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.cloud</groupId>\n                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n                <version>${revision}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.cloud</groupId>\n                <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>\n                <version>${revision}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.cloud</groupId>\n                <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n                <version>${revision}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.cloud</groupId>\n                <artifactId>spring-cloud-starter-bus-rocketmq</artifactId>\n                <version>${revision}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.cloud</groupId>\n                <artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>\n                <version>${revision}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.cloud</groupId>\n                <artifactId>spring-cloud-alibaba-commons</artifactId>\n                <version>${revision}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba.cloud</groupId>\n                <artifactId>spring-cloud-starter-alibaba-schedulerx</artifactId>\n                <version>${revision}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba</groupId>\n                <artifactId>druid-spring-boot-starter</artifactId>\n                <version>${druid.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba</groupId>\n                <artifactId>druid</artifactId>\n                <version>${druid.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.mybatis.spring.boot</groupId>\n                <artifactId>mybatis-spring-boot-starter</artifactId>\n                <version>${mybatis.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.logging.log4j</groupId>\n                <artifactId>log4j-core</artifactId>\n                <version>${log4j-core.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.slf4j</groupId>\n                <artifactId>slf4j-api</artifactId>\n                <version>${slf4j-api.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.alibaba</groupId>\n                <artifactId>fastjson</artifactId>\n                <version>${fastjson.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.apache.logging.log4j</groupId>\n                <artifactId>log4j-slf4j2-impl</artifactId>\n                <version>${log4j-slf4j2-impl.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.google.guava</groupId>\n                <artifactId>guava</artifactId>\n                <version>${guava.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.projectlombok</groupId>\n                <artifactId>lombok</artifactId>\n                <version>${lombok.version}</version>\n            </dependency>\n        </dependencies>\n    </dependencyManagement>\n\n\t<!-- Override org.springframework.cloud:spring-cloud-dependencies-parent distributionManagement -->\n\t<distributionManagement>\n\t\t<snapshotRepository>\n\t\t\t<id>github</id>\n\t\t\t<url>https://maven.pkg.github.com/alibaba/spring-cloud-alibaba</url>\n\t\t</snapshotRepository>\n\t</distributionManagement>\n\n    <profiles>\n        <profile>\n            <id>release</id>\n            <build>\n                <plugins>\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-source-plugin</artifactId>\n                        <version>${maven-source-plugin.version}</version>\n                        <executions>\n                            <execution>\n                                <phase>package</phase>\n                                <goals>\n                                    <goal>jar-no-fork</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-javadoc-plugin</artifactId>\n                        <version>${maven-javadoc-plugin.version}</version>\n                        <executions>\n                            <execution>\n                                <phase>package</phase>\n                                <goals>\n                                    <goal>jar</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-gpg-plugin</artifactId>\n                        <version>${maven-gpg-plugin.version}</version>\n                        <executions>\n                            <execution>\n                                <phase>verify</phase>\n                                <goals>\n                                    <goal>sign</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n\n                    <plugin>\n                        <groupId>org.codehaus.mojo</groupId>\n                        <artifactId>flatten-maven-plugin</artifactId>\n                        <version>${flatten-maven-plugin.version}</version>\n                        <configuration>\n                            <updatePomFile>true</updatePomFile>\n                            <flattenMode>resolveCiFriendliesOnly</flattenMode>\n                        </configuration>\n                        <executions>\n                            <execution>\n                                <id>flatten</id>\n                                <phase>process-resources</phase>\n                                <goals>\n                                    <goal>flatten</goal>\n                                </goals>\n                            </execution>\n                            <execution>\n                                <id>flatten.clean</id>\n                                <phase>clean</phase>\n                                <goals>\n                                    <goal>clean</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n\n                    <plugin>\n                        <groupId>org.sonatype.central</groupId>\n                        <artifactId>central-publishing-maven-plugin</artifactId>\n                        <version>${central.publishing.maven.version}</version>\n                        <extensions>true</extensions>\n                        <configuration>\n                            <publishingServerId>central</publishingServerId>\n                        </configuration>\n                    </plugin>\n                </plugins>\n            </build>\n        </profile>\n    </profiles>\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/config-init/config/datasource-config.yaml",
    "content": "spring:\n  datasource:\n    driver-class-name: com.mysql.jdbc.Driver\n    username: 'root'\n    password: 'root'\n  main:\n    allow-bean-definition-overriding: true\nmybatis:\n  configuration:\n    map-underscore-to-camel-case: true"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/config-init/config/integrated-account.yaml",
    "content": "spring:\n  datasource:\n    url: jdbc:mysql://integrated-mysql:3306/integrated_account?useSSL=false&characterEncoding=utf8"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/config-init/config/integrated-consumer.yaml",
    "content": "spring:\n  datasource:\n    url: jdbc:mysql://integrated-mysql:3306/integrated_praise?useSSL=false&characterEncoding=utf8\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      bindings:\n        consumer-in-0:\n          destination: PRAISE-TOPIC-01\n          content-type: application/json\n          group: praise-consumer-group-PRAISE-TOPIC-01\n      rocketmq:\n        binder:\n          name-server: rocketmq:9876\n        bindings:\n          consumer-in-0:\n            consumer:\n              pullInterval: 4000\n              pullBatchSize: 4\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/config-init/config/integrated-gateway.yaml",
    "content": "spring:\n  cloud:\n    gateway:\n      routes:\n        - id: placeOrder\n          uri: lb://integrated-order\n          predicates:\n            - Path=/order/create\n        - id: queryStorage\n          uri: lb://integrated-storage\n          predicates:\n            - Path=/storage/\n        - id: queryAccount\n          uri: lb://integrated-account\n          predicates:\n            - Path=/account/\n        - id: praiseItemRocketMQ\n          uri: lb://integrated-provider\n          predicates:\n            - Path=/praise/rocketmq\n        - id: praiseItemSentinel\n          uri: lb://integrated-provider\n          predicates:\n            - Path=/praise/sentinel\n        - id: queryPraise\n          uri: lb://integrated-consumer\n          predicates:\n            - Path=/praise/query"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/config-init/config/integrated-order.yaml",
    "content": "spring:\n  datasource:\n    url: jdbc:mysql://integrated-mysql:3306/integrated_order?useSSL=false&characterEncoding=utf8"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/config-init/config/integrated-provider.yaml",
    "content": "spring:\n  cloud:\n    stream:\n      bindings:\n        praise-output:\n          destination: PRAISE-TOPIC-01\n          content-type: application/json\n      rocketmq:\n        binder:\n          name-server: rocketmq:9876\n        bindings:\n          praise-output:\n            producer:\n              group: test"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/config-init/config/integrated-storage.yaml",
    "content": "spring:\n  datasource:\n    url: jdbc:mysql://integrated-mysql:3306/integrated_storage?useSSL=false&characterEncoding=utf8"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/config-init/rocketmq/broker.conf",
    "content": "# Licensed to the Apache Software Foundation (ASF) under one or more\n# contributor license agreements.  See the NOTICE file distributed with\n# this work for additional information regarding copyright ownership.\n# The ASF licenses this file to You under the Apache License, Version 2.0\n# (the \"License\"); you may not use this file except in compliance with\n# 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, 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\nbrokerIP1=172.20.0.4\nbrokerClusterName = DefaultCluster\nbrokerName = broker-a\nbrokerId = 0\ndeleteWhen = 04\nfileReservedTime = 48\nbrokerRole = ASYNC_MASTER\nflushDiskType = ASYNC_FLUSH\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/config-init/scripts/nacos-config-quick.sh",
    "content": "#!/bin/sh\necho \"Nacos auto config started\"\ndatasourceConfig=$(cat ../config/datasource-config.yaml)\nstorageConfig=$(cat ../config/integrated-storage.yaml)\naccountConfig=$(cat ../config/integrated-account.yaml)\norderConfig=$(cat ../config/integrated-order.yaml)\ngatewayConfig=$(cat ../config/integrated-gateway.yaml)\nproviderConfig=$(cat ../config/integrated-provider.yaml)\nconsumerConfig=$(cat ../config/integrated-consumer.yaml)\ngroupId=\"integrated-example\"\ncurl -X POST \"nacos-server:8848/nacos/v1/cs/configs\" -d \"dataId=datasource-config.yaml&group=${groupId}&content=${datasourceConfig}\"\ncurl -X POST \"nacos-server:8848/nacos/v1/cs/configs\" -d \"dataId=integrated-storage.yaml&group=${groupId}&content=${storageConfig}\"\ncurl -X POST \"nacos-server:8848/nacos/v1/cs/configs\" -d \"dataId=integrated-account.yaml&group=${groupId}&content=${accountConfig}\"\ncurl -X POST \"nacos-server:8848/nacos/v1/cs/configs\" -d \"dataId=integrated-order.yaml&group=${groupId}&content=${orderConfig}\"\ncurl -X POST \"nacos-server:8848/nacos/v1/cs/configs\" -d \"dataId=integrated-gateway.yaml&group=${groupId}&content=${gatewayConfig}\"\ncurl -X POST \"nacos-server:8848/nacos/v1/cs/configs\" -d \"dataId=integrated-provider.yaml&group=${groupId}&content=${providerConfig}\"\ncurl -X POST \"nacos-server:8848/nacos/v1/cs/configs\" -d \"dataId=integrated-consumer.yaml&group=${groupId}&content=${consumerConfig}\"\necho \"Nacos config pushed successfully finished\""
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/config-init/sql/init.sql",
    "content": "-- Storage库存微服务的数据库业务初始化\nDROP DATABASE IF EXISTS integrated_storage;\nCREATE DATABASE integrated_storage;\nUSE integrated_storage;\nCREATE TABLE `storage`\n(\n    `id`             bigint(11) unsigned NOT NULL AUTO_INCREMENT,\n    `commodity_code` varchar(255) DEFAULT NULL,\n    `count`          int(11)      DEFAULT '0',\n    `create_time`    datetime     DEFAULT NULL,\n    `update_time`    datetime     DEFAULT NULL,\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `commodity_code` (`commodity_code`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 2\n  DEFAULT CHARSET = utf8;\nINSERT INTO `storage`\nVALUES ('1', '1', '100', '2022-08-07 22:48:29', '2022-08-14 13:49:05');\n\n-- Account账户微服务的数据库业务初始化\nDROP DATABASE IF EXISTS integrated_account;\nCREATE DATABASE integrated_account;\nUSE integrated_account;\nCREATE TABLE `account`\n(\n    `id`          bigint(11) unsigned NOT NULL AUTO_INCREMENT,\n    `user_id`     varchar(255) DEFAULT NULL,\n    `money`       int(11)      DEFAULT '0',\n    `create_time` datetime     DEFAULT NULL,\n    `update_time` datetime     DEFAULT NULL,\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 2\n  DEFAULT CHARSET = utf8;\nINSERT INTO `account`\nVALUES ('1', 'admin', '3', '2022-08-07 22:53:01', '2022-08-14 13:49:05');\n\n-- Order订单微服务的数据库业务初始化\nDROP DATABASE IF EXISTS integrated_order;\nCREATE DATABASE integrated_order;\nUSE integrated_order;\nCREATE TABLE `order`\n(\n    `id`             bigint(11) unsigned NOT NULL AUTO_INCREMENT,\n    `user_id`        varchar(255) DEFAULT NULL,\n    `commodity_code` varchar(255) DEFAULT NULL,\n    `count`          int(11)      DEFAULT NULL,\n    `money`          int(11)      DEFAULT '0',\n    `create_time`    datetime     DEFAULT NULL,\n    `update_time`    datetime     DEFAULT NULL,\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 16\n  DEFAULT CHARSET = utf8;\n\n-- 点赞业务的数据库初始化\nDROP DATABASE IF EXISTS integrated_praise;\nCREATE DATABASE integrated_praise;\nUSE integrated_praise;\nCREATE TABLE `item`\n(\n    `id`          bigint(11) unsigned NOT NULL AUTO_INCREMENT,\n    `praise`      int(11)  DEFAULT NULL,\n    `create_time` datetime DEFAULT NULL,\n    `update_time` datetime DEFAULT NULL,\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 2\n  DEFAULT CHARSET = utf8;\nINSERT INTO `item`\nVALUES ('1', '0', '2022-08-14 00:33:50', '2022-08-14 14:07:34');\n-- Storage库存微服务的数据库Seata初始化\nUSE integrated_storage;\nCREATE TABLE `undo_log`\n(\n    `id`            bigint(20)   NOT NULL AUTO_INCREMENT,\n    `branch_id`     bigint(20)   NOT NULL,\n    `xid`           varchar(100) NOT NULL,\n    `context`       varchar(128) NOT NULL,\n    `rollback_info` longblob     NOT NULL,\n    `log_status`    int(11)      NOT NULL,\n    `log_created`   datetime     NOT NULL,\n    `log_modified`  datetime     NOT NULL,\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8;\n\n-- Storage库存微服务的数据库Seata初始化\nUSE integrated_account;\nCREATE TABLE `undo_log`\n(\n    `id`            bigint(20)   NOT NULL AUTO_INCREMENT,\n    `branch_id`     bigint(20)   NOT NULL,\n    `xid`           varchar(100) NOT NULL,\n    `context`       varchar(128) NOT NULL,\n    `rollback_info` longblob     NOT NULL,\n    `log_status`    int(11)      NOT NULL,\n    `log_created`   datetime     NOT NULL,\n    `log_modified`  datetime     NOT NULL,\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8;\n\n-- Storage库存微服务的数据库Seata初始化\nUSE integrated_order;\nCREATE TABLE `undo_log`\n(\n    `id`            bigint(20)   NOT NULL AUTO_INCREMENT,\n    `branch_id`     bigint(20)   NOT NULL,\n    `xid`           varchar(100) NOT NULL,\n    `context`       varchar(128) NOT NULL,\n    `rollback_info` longblob     NOT NULL,\n    `log_status`    int(11)      NOT NULL,\n    `log_created`   datetime     NOT NULL,\n    `log_modified`  datetime     NOT NULL,\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8;"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/docker-compose/docker-compose-env.yml",
    "content": "version: \"3\"\nservices:\n\n  # nacos\n  nacos:\n    image: nacos/nacos-server:v3.1.0\n    hostname: nacos-server\n    restart: always\n    container_name: integrated-example-nacos\n    environment:\n      - PREFER_HOST_MODE=hostname\n      - MODE=standalone\n    ports:\n      - \"8848:8848\"\n\n  # mysql\n  mysql:\n    container_name: integrated-example-mysql\n    hostname: integrated-mysql\n    restart: always\n    image: mysql:5.7\n    environment:\n      MYSQL_ROOT_PASSWORD: root\n      MYSQL_DATABASE: integrated_storage\n    ports:\n      - \"3306:3306\"\n    volumes:\n      - ../config-init/sql/init.sql:/docker-entrypoint-initdb.d/init.sql\n    command:\n      [\n        --character-set-server=utf8mb4,\n        --collation-server=utf8mb4_unicode_ci\n      ]\n\n  # rocketMQ\n  rmqnamesrv:\n    image: apache/rocketmq:4.9.4\n    hostname: rocketmq\n    restart: always\n    container_name: integrated-example-rmqnamesrv\n    ports:\n      - \"9876:9876\"\n    command: sh mqnamesrv\n\n  rmqbroker:\n    image: apache/rocketmq:4.9.4\n    restart: always\n    container_name: integrated-example-rmqbroker\n    ports:\n      - \"10909:10909\"\n      - \"10911:10911\"\n    volumes:\n      - ../config-init/rocketmq/broker.conf:/opt/rocketmq-4.9.4/conf/broker.conf\n    environment:\n      NAMESRV_ADDR: \"rmqnamesrv:9876\"\n      JAVA_OPTS: \" -Duser.home=/opt\"\n      JAVA_OPT_EXT: \"-server -Xms128m -Xmx128m -Xmn128m\"\n    command: sh mqbroker -c /opt/rocketmq-4.9.4/conf/broker.conf\n    depends_on:\n      - rmqnamesrv\n\n  # seata\n  seata-server:\n    image: seataio/seata-server:1.5.1\n    hostname: seata-server\n    restart: always\n    container_name: integrated-example-seata-server\n    ports:\n      - \"8091:8091\"\n    environment:\n      - SEATA_PORT=8091\n      - STORE_MODE=file\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/docker-compose/docker-compose-service.yml",
    "content": "version: \"3\"\nservices:\n\n  # integrated example module\n  integrated-frontend:\n    image: integrated-frontend\n    hostname: integrated-frontend\n    build:\n      dockerfile: ./integrated-frontend/Dockerfile\n      context: ../\n    env_file:\n      - .env\n    container_name: integrated-frontend\n    ports:\n      - ${FRONTEND_PORT}:${FRONTEND_PORT}\n    depends_on:\n      - integrated-gateway\n      - integrated-account\n      - integrated-order\n      - integrated-storage\n      - integrated-praise-consumer\n      - integrated-praise-provider\n\n  integrated-gateway:\n    image: integrated-gateway\n    hostname: gateway-service\n    build:\n      dockerfile: ./integrated-gateway/Dockerfile\n      context: ../\n    env_file:\n        - .env\n    container_name: integrated-gateway\n    ports:\n      - ${GATEWAY_PORT}:${GATEWAY_PORT}\n\n  integrated-account:\n    image: integrated-account\n    build:\n      dockerfile: ./integrated-account/Dockerfile\n      context: ../\n    env_file:\n        - .env\n    container_name: integrated-account\n    ports:\n      - ${ACCOUNT_PORT}:${ACCOUNT_PORT}\n\n  integrated-order:\n    image: integrated-order\n    build:\n      dockerfile: ./integrated-order/Dockerfile\n      context: ../\n    env_file:\n        - .env\n    container_name: integrated-order\n    ports:\n      - ${ORDER_PORT}:${ORDER_PORT}\n\n  integrated-storage:\n    image: integrated-storage\n    build:\n      dockerfile: ./integrated-storage/Dockerfile\n      context: ../\n    env_file:\n        - .env\n    container_name: integrated-storage\n    ports:\n      - ${STORAGE_PORT}:${STORAGE_PORT}\n\n  integrated-praise-provider:\n    image: integrated-praise-provider\n    build:\n      dockerfile: ./integrated-praise-provider/Dockerfile\n      context: ../\n    env_file:\n        - .env\n    container_name: integrated-praise-provider\n    ports:\n      - ${PRAISE_PROVIDER_PORT}:${PRAISE_PROVIDER_PORT}\n\n  integrated-praise-consumer:\n    image: integrated-praise-consumer\n    build:\n      dockerfile: ./integrated-praise-consumer/Dockerfile\n      context: ../\n    env_file:\n        - .env\n    container_name: integrated-praise-consumer\n    ports:\n      - ${PRAISE_CONSUMER_PORT}:${PRAISE_CONSUMER_PORT}\n    depends_on:\n      - integrated-praise-provider\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/docs/en/docker-compose-deployment.md",
    "content": "# Spring Cloud Alibaba Containerized Deployment Best Practices | Docker-Compose Edition\n\n## Preparation\n\nIf you have not installed Docker or Docker-Compose, please follow the official documentation to build the environment\n\n> Note: When using Docker-Compose to experience the demo, please make sure that the local machine memory resource is >= 24G!\n\n- Docker：https://docs.docker.com/desktop/install/linux-install/\n- Docker-Compose：https://docs.docker.com/compose/install/\n\n### Hosts configuration\n\nTo ensure that the code can start properly, please configure the local host mapping first, add the following mapping to the configuration file.\n\n```shell\n# for integrated-example\n127.0.0.1 integrated-mysql\n127.0.0.1 nacos-server\n127.0.0.1 seata-server\n127.0.0.1 rocketmq\n127.0.0.1 gateway-service\n127.0.0.1 integrated-frontend\n```\n\n### Preparing jar packages\n\nGo to the `spring-cloud-alibaba-examples` directory and run the `mvn package` command to compile the project and generate the jar package, so as to prepare for the subsequent construction of the docker service image.\n\n## Quickly start \n\n### Component start\n\nEnter `spring-cloud-alibaba-examples/integration-example` directory, run the following command in the terminal to quickly deploy the components required to run example: `docker-compose -f ./docker-compose/docker-compose-env.yml up -d`.\n\n### Add configuration\n\nAfter docker-compose-env.yml is run successfully, add the Nacos configuration:\n\n- Enter `spring-cloud-alibaba-examples/integration-example` directory;\n- Execute the `config-init/scripts/nacos-config-quick.sh` script file in the terminal.\n\nThe one-click import of all micro-service configurations is complete.\n\n> Note: windows operating systems can use `git bash` to execute shell script files to complete the configuration import.\n\n### Service start\n\nEnter `spring-cloud-alibaba-examples/integration-example` directory, Run the following command in the terminal to quickly deploy the services required for running example: `docker-compose -f ./docker-compose/docker-compose-service.yml up -d`.\n\n## Stop all containers\n\n### Stops the service container\n\nEnter `spring-cloud-alibaba-examples/integration-examplee` directory, Run the following command in the terminal to `docker-compose -f ./docker-compose/docker-compose-service.yml down` to stop the running example service container.\n\n### Stops the component container\n\nEnter `spring-cloud-alibaba-examples/integration-example` directory, Run the following command in the terminal to `docker-compose -f ./docker-compose/docker-compose-env.yml down` to stop the running example component container.\n\n> When the container starts, you can observe the startup process of the container through `docker-compose- f docker-compose-*.yml up` !\n\n## Experience Demo\n\n### Distributed Transaction Capabilities\n\n#### Scenario Description\n\nFor the distributed transaction capability, we provide the scenario **where a user places an order for goods** and after placing the order.\n\n- First request the inventory module and deduct the inventory\n- Deduct the account balance\n- Generate order information to return a response\n\n#### Start test\n\nVisit `http://integrated-frontend:8080/order` to experience the corresponding scenario.\n\nBy clicking the order button directly to submit the form, we simulate the client sending a request to the gateway to create an order.\n\n- The user's userId is admin\n- The item number of the user's order is 1\n- The number of items purchased in this order is 1\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016155416524.png)\n\nIn this demo example, the unit price of each item is 2 for demonstration purposes.\n\nAnd in the previous preparation, **initialize business database table** we created a new user userId = admin with a balance of $3, and a new item numbered 1 with 100 units in stock.\n\nSo by doing the above, we will create an order, deduct the number of items in stock corresponding to item number 1 (100-1=99), and deduct the balance of the admin user (3-2=1).\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016155429801.png)\n\nIf the same interface is requested again, again the inventory is deducted first (99-1=98), but an exception is thrown because the admin user's balance is insufficient and is caught by Seata, which performs a two-stage commit of the distributed transaction and rolls back the transaction.\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016155436112.png)\n\nYou can see that the database still has 99 records in stock because of the rollback.\n\n### Fused flow limiting, peak shaving capability\n\n#### Scenario Description\n\nFor service fusion limiting and peak and valley cutting in the context of high traffic, we provide a scenario **where users make likes for products**. In this scenario, we provide two ways to deal with high traffic.\n\n- Sentinel binds specified gateway routes on the gateway side for fusion degradation of services.\n- RocketMQ performs traffic clipping, where the producer sends messages to RocketMQ under high traffic requests, while the consumer pulls and consumes through a configurable consumption rate, reducing the pressure of high traffic direct requests to the database to increase the number of likes requests.\n\n#### Start test\n\n- Sentinel service meltdown degradation\n\nVisit `http://integrated-frontend:8080/sentinel` to experience the corresponding scenario.\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016155501290.png)\n\nThe Gateway routing point service has a flow limit rule of 5, while 10 concurrent requests are simulated on the front end through asynchronous processing.\n\nTherefore, we can see that Sentinel performs a service fusion on the Gateway side to return the fallback to the client for the extra traffic, while the number of likes in the database is updated (+5).\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20220914155755103.png)\n\n- RocketMQ is performing peak and valley reduction\n\nVisit `http://integrated-frontend:8080/rocketmq` to experience the corresponding scenario.\n\nSince we previously configured the consumption rate and interval of the `integrated-praise-consumer` consumer module in Nacos, we simulate 1000 requests for likes at the click of a button, and the `integrated-praise-provider`\nwill deliver 1000 requests to the Broker, and the consumer module will consume them according to the configured consumption rate, and update the database with the product data of the likes, simulating the characteristics of RocketMQ to cut the peaks and fill the valleys under high traffic.\n\nYou can see that the number of likes in the database is being dynamically updated.\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016173604059.png)\n\n## Other\n\nThis example **is just a selection of typical features for each component to serve the application scenario**.\n\nIf you are interested or want to go deeper, you are welcome to study the individual example documentation for each component.\n\n- Nacos examples\n    - [Nacos config example](../../../nacos-example/readme.md)\n    - [Nacos discovery example](../../../nacos-example/readme.md)\n- [Sentinel core example](../../../sentinel-example/README.md)\n- [Seata example](../../../seata-example/readme.md)\n- [RocketMQ example](../../../rocketmq-example/readme.md)\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/docs/en/kubernetes-deployment.md",
    "content": "# Spring Cloud Alibaba Containerized Deployment Best Practices | Kubernetes Helm-Chart Edition\n\n## Preparation\n\nThis is the Spring Cloud Alibaba (hereinafter referred to as SCA) Best Practices Kubernetes deployment version, which requires you to prepare the following environment.\n\n- Kubernetes (We recommend using Docker Desktop's built-in integrated Kubernetes environment for this experience.)\n- Helm\n\nIf the test machine does not already have the above environment, please go to the official documentation to build the environment.\n\n- [Helm Installation](https://helm.sh/zh/docs/intro/install/)\n- [Kubernetes Docker Desktop Quick Installation](https://docs.docker.com/desktop/kubernetes/)\n\nHere expose the services of the Pod in Kubernetes to the outside world by means of NodePort, and configure the ip mapping of the Kubernetes cluster node before starting the test.\n```shell\n# Please adjust with the public ip of your K8S node\n120.24.xxx.xxx integrated-frontend\n120.24.xxx.xxx gateway-service\n120.24.xxx.xxx integrated-mysql-web\n120.24.xxx.xxx nacos-mysql-web\n120.24.xxx.xxx nacos-svc\n```\n\n## Start the test\n\nGo to the ``spring-cloud-alibaba-examples/integrated-example`` directory and execute the following command to deploy the application using Helm.\n```shell\nhelm package helm-chart\n\nhelm install integrated-example integrated-example-1.0.0.tgz\n```\nBy running the above command, quickly deploy the best practice example through Helm according to the Helm Chart documentation provided by the SCA community.\n\nYou can check the deployment status of each container resource through the `kubectl` command provided by Kubernetes, and wait patiently for **all containers to finish starting** to experience the usage scenarios and capabilities of each component on the corresponding page.\n\nIf you want to stop the experience, enter the following command.\n```shell\nhelm uninstall integrated-example\n```\n\n### Distributed Transaction Capabilities\n\n#### Scenario Description\n\nFor the distributed transaction capability, SCA community provide a scenario **where a user places an order to purchase goods** and after placing the order.\n\n- First request the inventory module and deduct the inventory\n- Deduct the account balance\n- Generate order information to return a response\n\n##### Start test\n\nVisit `http://integrated-frontend:30080/order` to experience the corresponding scenario.\n\nBy clicking directly on the order button to submit the form, simulate the client sending a request to the gateway to create an order.\n\n- The user's userId is admin\n- The user places an order with item number 1\n- The number of items purchased in this order is 1\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016143033445.png)\n\nIn this demo example, the unit price of each item is 2 for demonstration purposes.\n\nWhile initializing the `integrated-mysql` container, **initializing the business database table** creates a new user, the user's userId is admin, with a balance of $3; and a new item numbered 1 with 100 units in stock.\nSo by doing the above, application will create an order, deduct the number of items in stock corresponding to item number 1 (100-1=99), and deduct the balance of the admin user (3-2=1).\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016143057730.png)\n\nIf the same interface is requested again, again the inventory is deducted first (99-1=98), but an exception is thrown because the admin user's balance is insufficient and is caught by Seata, which performs a two-stage commit of the distributed transaction and rolls back the transaction.\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016143104810.png)\n\nYou can see that the database still has 99 records in stock because of the rollback.\n\n### Fused flow limiting, peak shaving capability\n\n#### Scenario Description\n\nFor service fusion limiting and peak and valley cutting in the context of high traffic, SCA community provide a scenario** where users make likes for products**. In this scenario, we provide two ways to deal with high traffic.\n\n- Sentinel binds specified gateway routes on the gateway side for fusion degradation of services.\n- RocketMQ performs traffic clipping, where the producer sends messages to RocketMQ under high traffic requests, while the consumer pulls and consumes through a configurable consumption rate, reducing the pressure of high traffic direct requests to the database to increase the number of likes requests.\n\n#### Startup test\n\n- Sentinel Service Meltdown Degradation\n\nVisit `http://integrated-frontend:30080/sentinel` to experience the corresponding scenario.\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016143120697.png)\n\nThe Gateway routing point service has a flow limit rule of 5, while 10 concurrent requests are simulated on the front end through asynchronous processing.\n\nTherefore, we can see that Sentinel performs a service fusion on the Gateway side to return the fallback to the client for the extra traffic, while the number of likes in the database is updated (+5).\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016143203773.png)\n\n- RocketMQ is performing peak and valley reduction\n\nVisit `http://integrated-frontend:30080/rocketmq` to experience the corresponding scenario.\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016143342664.png)\n\nSince the consumption rate and interval of the `integrated-praise-consumer` consumer module is configured in Nacos before, the application will simulate 1000 \"like\" requests when clicking the button, `integrated-praise-provider`\nwill deliver 1000 requests to the Broker, and the consumer module will consume them according to the configured consumption rate, and update the database with the product data of the likes, simulating the characteristics of RocketMQ to cut the peaks and fill the valleys under high traffic.\n\nYou can see that the number of likes in the database is being dynamically updated.\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016143352619.png)\n\n## Other\n\nThis example **is just a selection of typical features for each component to serve the application scenario**.\n\nOf course, there is more to each component than just what is demonstrated in the best practices, so if you are interested or want to go deeper, feel free to read the individual example documentation for each component.\n\n- Nacos examples\n  - [Nacos config example](../../../nacos-example/readme.md)\n  - [Nacos discovery example](../../../nacos-example/readme.md)\n- [Sentinel core example](../../../sentinel-example/README.md)\n- [Seata example](../../../seata-example/readme.md)\n- [RocketMQ example](../../../rocketmq-example/readme.md)"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/docs/en/local-deployment.md",
    "content": "# Spring Cloud Alibaba Containerized Deployment Best Practices | Local Deployment Edition\n\n## Preparation\n\n### Environment Declaration\n\nBefore running the local example, you need to ensure that the local machine has the following basic environment. If you do not have the current local environment, the following steps to demonstrate the construction process.\nYou can also quickly launch the component through the docker-compose file provided by the Spring Cloud Alibaba (SCA) community.\n\n- Nacos server\n- Seata server\n- RocketMQ server\n- MySQL server\n\n### Component Service Versions\n\nFor each component version of this project, please go to the release page of each community to download and decompression run.\n\n- [Nacos: version 2.1.0](https://github.com/alibaba/nacos/releases)\n- [Seata: version 1.5.1](https://github.com/seata/seata/releases)\n- [RocketMQ: version 4.9.4](https://github.com/apache/rocketmq/releases)\n- MySQL: version 5.7\n\n### Hosts configuration\n\nTo ensure that the code can start properly, please configure the local host mapping first, add the following mapping to the configuration file.\n\n```shell\n# for integrated-example\n127.0.0.1 integrated-mysql\n127.0.0.1 nacos-server\n127.0.0.1 seata-server\n127.0.0.1 rocketmq\n127.0.0.1 gateway-service\n127.0.0.1 integrated-frontend\n```\n\n### Database configuration\n\nBefore you start the database configuration, please make sure the MySQL server is on.\n\n#### Initialize business tables\n\nFor the first scenario, the order, account, and inventory microservices all need their own databases, while the second scenario simulates a database for storing like information as well.\n\nRun the sql script `spring-cloud-alibaba-examples/integrated-example/config-init/sql/init.sql` to create the environment required for the business and the Seata-related tables in one click.\n\n### Nacos Configuration\n\nAt this point, the database services are configured and you need to configure the Nacos configuration center for all the microservice configuration files.\n\n#### Nacos startup\n\nFor the sake of example, here we use the ``standalone`` mode of Nacos, go to the unpacked directory of Nacos and execute the following command.\n\n```shell\n#Linux/Mac environment\nsh bin/startup.sh -m standalone\n#If you are in Ubuntu and the above command gives you an error [[symbol not found, you can run the following command\nbash bin/startup.sh -m standalone\n#Win environment\n. \\bin\\startup.cmd -m standalone\n````\n\n#### Adding configuration files\n\nBefore bulk importing the configuration, please modify the datasource configuration (username and password) in `spring-cloud-alibaba-examples/integrated-example/config-init/config/datasource-config.yaml`.\n\nAfter that, run `spring-cloud-alibaba-examples/integrated-example/config/scripts/nacos-config-quick.sh` to complete the one-click import of all microservice configurations.\n\n```shell\n# linux\nsh nacos-config-quick.sh\n# windows can use git bash to import the configuration, run the command as above\n```\n\n### Seata Configuration\n\nAfter the Nacos service registry and configuration center are deployed, here is the configuration of the Seata server.\n\nSeata's db mode requires additional configuration of database information and modification of the Seata Server configuration file, and the configuration file has been merged in the new version compared to the old version, so for demonstration purposes, Seata Server is started in `file` mode on Seata standalone.\n\n#### Start Seata Server\n\nGo to the seata directory after the release and execute the following command.\n\n```shell\n#Linux/Mac environment\nsh . /bin/seata-server.sh\n#Win environment\nbin\\seata-server.bat\n```\n\n### RocketMQ configuration\n\nAfter the Seata service starts, you can start the RocketMQ NameServer and Broker services.\n\nGo to the unpacked rocketmq directory after the release and execute the following command.\n\n#### Start the NameServer\n\n```shell\n#Linux/Mac environment\nsh bin/mqnamesrv\n#Win environment\n. \\bin\\mqnamesrv.cmd\n```\n\n#### Start Broker\n\n```shell\n#Linux/Mac environment\nsh bin/mqbroker\n#Win environment\n. \\bin\\mqbroker.cmd\n```\n\n## Run the demo example\n\nAfter the preparation work is done, you can run the demo, mainly according to different usage scenarios, you can experience the user order (distributed transaction capability) and simulate the high traffic point (meltdown and limit the flow as well as the ability to cut the peak and fill the valley) respectively.\n\nFirst, you need to start the `integrated-frontend` and `integrated-gateway` projects separately.\n\n- `integrated-frontend` module is front page for best practice examples.\n- `integral-gateway` module is the gateway for the entire best practice example.\n\n### Distributed Transaction Capabilities\n\n#### Scenario Description\n\nFor the distributed transaction capability, we provide the scenario **where a user places an order for goods** and after placing the order.\n\n- First request the inventory module and deduct the inventory\n- Deduct the account balance\n- Generate order information to return a response\n\n##### Start test\n\nStart `integrated-storage`,`integrated-account`,`integrated-order` microservices respectively.\n\nVisit `http://integrated-frontend:8080/order` to experience the corresponding scenario.\n\nBy clicking the order button directly to submit the form, application simulate the client sending a request to the gateway to create an order.\n\n- The user's userId is admin\n- The item number of the user's order is 1\n- The number of items purchased in this order is 1\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016155416524.png)\n\nIn this demo example, the unit price of each item is 2 for demonstration purposes.\n\nAnd in the previous preparation, **initialize business database table** application created a new user, the user's userId is admin with a balance of $3, and a new item numbered 1 with 100 units in stock.\n\nSo by doing the above, we will create an order, deduct the number of items in stock corresponding to item number 1 (100-1=99), and deduct the balance of the admin user (3-2=1).\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016155429801.png)\n\nIf the same interface is requested again, again the inventory is deducted first (99-1=98), but an exception is thrown because the admin user's balance is insufficient and is caught by Seata, which performs a two-stage commit of the distributed transaction and rolls back the transaction.\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016155436112.png)\n\nYou can see that the database still has 99 records in stock because of the rollback.\n\n### Fused flow limiting, peak shaving capability\n\n#### Scenario Description\n\nFor service fusion limiting and peak and valley cutting in the context of high traffic, SCA community provide a scenario **where users make likes for products**. In this scenario, we provide two ways to deal with high traffic.\n\n- Sentinel binds specified gateway routes on the gateway side for fusion degradation of services.\n- RocketMQ performs traffic clipping, where the producer sends messages to RocketMQ under high traffic requests, while the consumer pulls and consumes through a configurable consumption rate, reducing the pressure of high traffic direct requests to the database to increase the number of likes requests.\n\n#### Startup test\n\nStart the `integrated-praise-provider` and `integrated-praise-consumer` modules separately.\n\n- Sentinel service meltdown degradation\n\nVisit `http://integrated-frontend:8080/sentinel` to experience the corresponding scenario.\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016155501290.png)\n\nThe Gateway routing point service has a flow limit rule of 5, while 10 concurrent requests are simulated on the front end through asynchronous processing.\n\nTherefore, we can see that Sentinel performs a service fusion on the Gateway side to return the fallback to the client for the extra traffic, while the number of likes in the database is updated (+5).\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20220914155755103.png)\n\n- RocketMQ is performing peak and valley reduction\n\nVisit `http://integrated-frontend:8080/rocketmq` to experience the corresponding scenario.\n\nSince previously configured the consumption rate and interval of the `integrated-praise-consumer` consumer module in Nacos, simulate 1000 requests for likes at the click of a button, and the `integrated-praise-provider`\nwill deliver 1000 requests to the Broker, and the consumer module will consume them according to the configured consumption rate, and update the database with the product data of the likes, simulating the characteristics of RocketMQ to cut the peaks and fill the valleys under high traffic.\n\nYou can see that the number of likes in the database is being dynamically updated.\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016173604059.png)\n\n## Other\n\nThis example **is just a selection of typical features for each component to serve the application scenario**.\n\nIf you are interested or want to go deeper, you are welcome to study the individual example documentation for each component.\n\n- Nacos examples\n  - [Nacos config example](../../../nacos-example/readme.md)\n  - [Nacos discovery example](../../../nacos-example/readme.md)\n- [Sentinel core example](../../../sentinel-example/README.md)\n- [Seata example](../../../seata-example/readme.md)\n- [RocketMQ example](../../../rocketmq-example/readme.md)\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/docs/en/readme.md",
    "content": "# Integrated Example\n\n## Project Description\n\nThis project is a demo of Spring Cloud Alibaba (hereinafter referred to as SCA) containerized deployment best practices, and is an example project integrating SCA components (Nacos, Sentinel, Seata, RocketMQ).\n\nThe main components used and their usage features are as follows.\n\n- Spring Cloud Gateway: gateway\n- Nacos: configuration centre and service registry\n- Sentinel: fusion flow limiting\n- Seata: Distributed Transactions\n- RocketMQ: message queues for peak and valley reduction\n- Docker: Microservices Containerized Deployment\n- Kubernetes Helm Chart\n\n![Overall Overview](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20220816004541921.png)\n\n## Application Scenario Description\n\nIn this demo, SCA community provide two business scenarios.\n\n1) A scenario where a user places an order for goods and after placing the order.\n\n- First request the inventory module to deduct the inventory\n\n- Deduct the account balance\n\n- Generate order information and return a response\n\n2) The user likes the goods (simulating the producer-consumer application scenario of MQ) and returns the details (number of likes, etc.) after the goods have been liked.\n\n### Detailed description of the component\n\n1) In which the scenario where the user places an order for the goods mainly uses Seata to perform distributed transactions to represent the capabilities.\n\n2) The scenario where the user likes a product simulates a high traffic environment with Sentinel for flow limiting or RocketMQ for peak shaving. In this scenario, SCA community provide two ways to deal with high traffic.\n\n- Sentinel binds a specified gateway route on the gateway side for service fusion degradation.\n- RocketMQ performs peak-shaving, where producers send messages to RocketMQ and consumers pull and consume at configurable consumption rates, reducing the pressure of high traffic direct requests to the database and increasing the number of likes.\n\n#### Spring Cloud Gateway\n\nA gateway to the microservices module.\n\nSpring Cloud GateWay integrates with Nacos, enabling dynamic routing configuration.\n\nBy listening for changes to the Nacos configuration, the service gateway routing configuration is dynamically refreshed so that each time the routing information changes, there is no need to modify the configuration file and then restart the service.\n\n#### Nacos\n\nThe configuration centre for each microservice, the service registry.\n\n- Configuration Centre\n  - Shared configuration: MySQL data source related information configuration.\n\n- Registration Centre\n  - All microservice modules are registered to Nacos for service registration and discovery.\n  - Integration with Spring Cloud Gateway gateway.\n\n#### Seata\n\nSeata-based AT model for distributed transaction processing for the Inventory, Accounts and Orders modules.\n\nRoll back transactions whenever stock is low/account balance is low.\n\n#### Sentinel\n\nService fusion flow limiting for point and click scenarios.\n\nIntegrates Nacos Configuration Center with Spring Cloud Gateway to enable dynamic configuration of fused flow limiting rules for specified routing rules.\n\n#### RocketMQ\n\nUsed for peaks and valleys reduction of like service traffic.\n\nBy sending high volume like requests from the producer to the mq, the consumer module pulls from the mq and consumes them with a certain frequency, rather than simply fusing and limiting the degradation of the service directly, enabling RocketMQ's ability to shave peaks and valleys for high volume traffic.\n\n## Release Notes\n\nThis project provides a [local-deployment](local-deployment.md), [docker-compose version](docker-compose-deployment.md) and a [Kubernetes Helm-Chart version](kubernetes-deployment.md).\n\n- To learn how to configure the components and build the complete environment, we recommend learning the [local-deployment](local-deployment.md).\n\n- If you only want to run the sample code, avoid the tedious local environment construction process, and do not want to use the K8S cluster. You can try using [docker-compose version] (docker-compose-deployment.md).\n\n- If you want to quickly experience the components on a K8S cluster and skip the process of deploying each component, please check out the [Kubernetes Helm-Chart version](kubernetes-deployment.md)."
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/docs/zh/docker-compose-deploy-zh.md",
    "content": "# Spring Cloud Alibaba 容器化部署最佳实践 | Docker-Compose 版本\n\n## 准备工作\n\n> Note: 使用 Docker-Compose 方式体验 Demo 时，请确保本地机器内存资源 >= 24G！\n\n如果您还没有安装 Docker 和 Docker-Compose，请按照官方文档来构建运行环境：\n\n- Docker：https://docs.docker.com/desktop/install/linux-install/\n- Docker-Compose：https://docs.docker.com/compose/install/\n\n### Hosts 配置\n\n为确保代码能够正常启动，请先配置本地主机映射，将以下映射添加到配置文件中。\n\n```shell\n# for integrated-example\n127.0.0.1 integrated-mysql\n127.0.0.1 nacos-server\n127.0.0.1 seata-server\n127.0.0.1 rocketmq\n127.0.0.1 gateway-service\n127.0.0.1 integrated-frontend\n```\n\n### 准备 jar 包\n\n进入 `spring-cloud-alibaba-examples` 目录下，执行 `mvn package` 命令编译项目生成 jar 包，为后续 Docker 构建服务镜像做准备。\n\n## 快速启动\n\n### 组件启动\n\n进入 `spring-cloud-alibaba-examples/integrated-example` 目录下，在终端中执行以下命令 `docker-compose -f ./docker-compose/docker-compose-env.yml up -d` 来快速部署运行 example 所需组件。\n\n### 添加配置\n\ndocker-compose-env.yml 文件运行成功之后，添加 Nacos 配置：\n\n1. 进入 `spring-cloud-alibaba-examples/integrated-example` 目录下；\n2. 在终端中执行 `config-init/scripts/nacos-config-quick.sh` 脚本文件。\n\n完成所有微服务配置的一键导入。\n\n> 注意：windows 操作系统可以通过 `git bash` 执行 shell 脚本文件完成配置导入。\n\n### 服务启动\n\n进入 `spring-cloud-alibaba-examples/integrated-example` 目录下，在终端中执行以下命令 `docker-compose -f ./docker-compose/docker-compose-service.yml up -d` 来快速部署运行 example 所需服务。\n\n## 停止所有容器\n\n### 停止服务容器\n\n进入 `spring-cloud-alibaba-examples/integrated-example` 目录下，在终端中执行以下命令 `docker-compose -f ./docker-compose/docker-compose-service.yml down` 来停止正在运行的 example 服务容器。\n\n\n### 停止组件容器\n\n进入 `spring-cloud-alibaba-examples/integrated-example` 目录下，在终端中执行以下命令 `docker-compose -f ./docker-compose/docker-compose-env.yml down` 来停止正在运行的 example 组件容器。\n\n> 在容器启动时，可以通过 `docker-compose -f docker-compose-*.yml up` 观察容器的启动过程！\n\n## 体验 Demo\n\n### 分布式事务能力\n\n#### 场景说明\n\n针对分布式事务能力，SCA 社区提供了**用户下单购买货物的场景**，下单后：\n\n- 先请求库存模块，扣减库存\n- 扣减账户余额\n- 生成订单信息返回响应\n\n#### 启动测试\n\n访问 `http://integrated-frontend:8080/order` 来体验对应场景。\n\n直接点击下单按钮提交表单，应用模拟客户端向网关发送了一个创建订单的请求。\n\n- 用户的 userId 为 admin\n- 用户下单的商品编号为1号\n- 此次订单购买的商品个数为1个\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016155416524.png)\n\n在本 demo 示例中，为了便于演示，每件商品的单价都为2。\n\n而在前面的准备工作中，**初始化业务数据库表**的时候应用新建了一个用户，用户 userId 为 admin，余额为 3 元；同时新建了一个编号为 1 号的商品，库存为 100 件。\n\n因此通过上述的操作，应用会创建一个订单，扣减对应商品编号为 1 号的库存个数（100-1=99），扣减 admin 用户的余额（3-2=1）。\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016155429801.png)\n\n如果再次请求相同的接口，同样是先扣减库存（99-1=98），但是会因为 admin 用户余额不足而抛出异常，并被 Seata 捕获，执行分布式事务二阶段提交，回滚事务。\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016155436112.png)\n\n可以看到数据库中库存的记录因为回滚之后仍然为 99 件。\n\n### 熔断限流，削峰填谷能力\n\n#### 场景说明\n\n针对大流量背景下的服务熔断限流，削峰填谷，SCA 社区提供了**用户为商品进行点赞的场景**。在此场景下，SCA 社区提供了两种应对大流量的处理方式。\n\n- Sentinel 在网关侧绑定指定网关路由进行服务的熔断降级。\n- RocketMQ 进行流量削峰填谷，在大流量请求下，生产者向 RocketMQ 发送消息，而消费者则通过可配置的消费速率进行拉取消费，减少大流量直接请求数据库增加点赞请求的压力。\n\n#### 启动测试\n\n- Sentinel 服务熔断降级\n\n访问 `http://integrated-frontend:8080/sentinel` 体验对应场景。\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016155501290.png)\n\n网关路由点赞服务的限流规则为 5，而在前端通过异步处理模拟了 10 次并发请求。\n\n因此可以看到 Sentinel 在 Gateway 侧针对多出的流量进行了服务熔断返回 fallback 给客户端，同时数据库的点赞数进行了更新（+5）。\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20220914155755103.png)\n\n- RocketMQ 进行流量削峰填谷\n\n访问 `http://integrated-frontend:8080/rocketmq` 体验对应场景。\n\n由于之前在 Nacos 中配置了 `integrated-praise-consumer` 消费者模块的消费速率以及间隔，在点击按钮时应用模拟 1000 个点赞请求，针对 1000 个点赞请求，`integrated-praise-provider`\n会将 1000 次请求都向 Broker 投递消息，而在消费者模块中会根据配置的消费速率进行消费，向数据库更新点赞的商品数据，模拟大流量下 RocketMQ 削峰填谷的特性。\n\n可以看到数据库中点赞的个数正在动态更新。\n\n![image-20221016173604059](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016173604059.png)\n\n## 其他\n\n本示例**仅是针对各个组件选取出了较为典型的功能特性来服务应用场景**\n\n当然各个组件的功能特性不仅仅只包含最佳实践中演示的这些，如果您感兴趣或是想要深入了解，欢迎学习各个组件的独立 example 相关文档。\n\n- Nacos examples\n  - [Nacos config example](../../../nacos-example/readme.md)\n  - [Nacos discovery example](../../../nacos-example/readme.md)\n- [Sentinel core example](../../../sentinel-example/README-zh.md)\n- [Seata example](../../../seata-example/readme.md)\n- [RocketMQ example](../../../rocketmq-example/readme.md)\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/docs/zh/kubernetes-deployment-zh.md",
    "content": "# Spring Cloud Alibaba容器化部署最佳实践 | Kubernetes Helm-Chart 版本\n\n## 准备工作\n\n此版本为 Spring Cloud Alibaba （后文简称为SCA）最佳实践 Kubernetes 部署版本，运行示例需要准备如下环境：\n\n- Kubernetes（建议使用 Docker Desktop 内置集成的 Kubernetes 环境进行体验。）\n- Helm\n\n如果测试机器上还未具备如上环境，请移步至对应官方文档进行环境搭建。\n\n- [Helm 安装](https://helm.sh/zh/docs/intro/install/)\n- [Kubernetes Docker Desktop 快捷安装](https://docs.docker.com/desktop/kubernetes/)\n\n在这里通过 NodePort 的方式来向外界暴露 Kubernetes 中 Pod 的服务，在启动测试前还需配置好 Kubernetes 集群节点的 ip 映射。\n\n```sh\n# 实际情况请结合您的 K8S 节点的公网 ip 进行调整\n120.24.xxx.xxx integrated-frontend\n120.24.xxx.xxx gateway-service\n120.24.xxx.xxx integrated-mysql-web\n120.24.xxx.xxx nacos-mysql-web\n120.24.xxx.xxx nacos-svc\n```\n\n## 启动测试\n\n进入到 `spring-cloud-alibaba-examples/integrated-example` 目录下，执行如下命令利用 Helm 部署应用程序。\n```shell\nhelm package helm-chart\n\nhelm install integrated-example integrated-example-1.0.0.tgz\n```\n通过运行上述命令，根据SCA社区提供的 Helm Chart 文档通过 Helm 快速完成最佳实践示例的部署。\n\n可以通过 Kubernetes 提供的 `kubectl` 命令查看各容器资源部署的情况，耐心等待**所有容器完成启动后**即可到对应页面体验各个组件的使用场景及能力。\n\n如果您想停止体验，输入如下命令。\n```shell\nhelm uninstall integrated-example\n```\n\n### 分布式事务能力\n\n#### 场景说明\n\n针对分布式事务能力，SCA社区提供了**用户下单购买货物的场景**，下单后：\n\n- 先请求库存模块，扣减库存\n- 扣减账户余额\n- 生成订单信息返回响应\n\n##### 启动测试\n\n访问 `http://integrated-frontend:30080/order` 来体验对应场景。\n\n直接点击下单按钮提交表单，模拟客户端向网关发送了一个创建订单的请求。\n\n- 用户的 userId 为 admin\n- 用户下单的商品编号为1号\n- 此次订单购买的商品个数为1个\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016143033445.png)\n\n在本 demo 示例中，为了便于演示，每件商品的单价都为2。\n\n而在 `integrated-mysql` 容器的初始化时，**初始化业务数据库表**的时候新建了一个用户，用户的userId为admin，余额为 3 元；同时新建了一个编号为 1 号的商品，库存为 100 件。\n\n因此通过上述的操作，应用会创建一个订单，扣减对应商品编号为 1 号的库存个数（100-1=99），扣减 admin 用户的余额（3-2=1）。\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016143057730.png)\n\n如果再次请求相同的接口，同样是先扣减库存（99-1=98），但是会因为 admin 用户余额不足而抛出异常，并被 Seata 捕获，执行分布式事务二阶段提交，回滚事务。\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016143104810.png)\n\n可以看到数据库中库存的记录因为回滚之后仍然为 99 件。\n\n### 熔断限流，削峰填谷能力\n\n#### 场景说明\n\n针对大流量背景下的服务熔断限流，削峰填谷，SCA社区提供了**用户为商品进行点赞的场景**。在此场景下，SCA社区提供了两种应对大流量的处理方式。\n\n- Sentinel 在网关侧绑定指定网关路由进行服务的熔断降级。\n- RocketMQ 进行流量削峰填谷，在大流量请求下，生产者向 RocketMQ 发送消息，而消费者则通过可配置的消费速率进行拉取消费，减少大流量直接请求数据库增加点赞请求的压力。\n\n#### 启动测试\n\n- Sentinel 服务熔断降级\n\n访问 `http://integrated-frontend:30080/sentinel` 体验对应场景。\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016143120697.png)\n\n网关路由点赞服务的限流规则为 5，而在前端通过异步处理模拟了 10 次并发请求。\n\n因此可以看到 Sentinel 在 Gateway 侧针对多出的流量进行了服务熔断返回 fallback 给客户端，同时数据库的点赞数进行了更新（+5）。\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016143203773.png)\n\n- RocketMQ 进行流量削峰填谷\n\n访问 `http://integrated-frontend:30080/rocketmq` 体验对应场景。\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016143342664.png)\n\n由于之前在 Nacos 中配置了 `integrated-praise-consumer` 消费者模块的消费速率以及间隔，在点击按钮时应用将会模拟 1000 个点赞请求，针对 1000 个点赞请求，`integrated-praise-provider`\n会将 1000 次请求都向 Broker 投递消息，而在消费者模块中会根据配置的消费速率进行消费，向数据库更新点赞的商品数据，模拟大流量下 RocketMQ 削峰填谷的特性。\n\n可以看到数据库中点赞的个数正在动态更新。\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016143352619.png)\n\n## 其他\n\n本示例**仅是针对各个组件选取出了较为典型的功能特性来服务应用场景**。\n\n当然各个组件的功能特性不仅仅只包含最佳实践中演示的这些，如果您对SCA感兴趣或是想要深入了解SCA项目，欢迎阅览各个组件的独立 example 相关文档。\n\n- Nacos examples\n  - [Nacos config example](../../../nacos-example/readme.md)\n  - [Nacos discovery example](../../../nacos-example/readme.md)\n- [Sentinel core example](../../../sentinel-example/README-zh.md)\n- [Seata example](../../../seata-example/readme.md)\n- [RocketMQ example](../../../rocketmq-example/readme.md)\n- "
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/docs/zh/local-deployment-zh.md",
    "content": "# Spring Cloud Alibaba 容器化部署最佳实践 | 本地部署版本\n\n## 准备工作\n\n### 环境声明\n\n在运行本地示例之前，需要保证本机具备以下的基础环境，如果您的本地没有当前的环境，下面会一步步进行搭建，演示搭建过程。\n当然您也可以通过 Spring Cloud Alibaba （下文简称为SCA）社区提供的docker-compose文件快速启动相应组件。\n\n- Nacos 服务端\n- Seata 服务端\n- RocketMQ 服务端\n- MySQL 服务端\n\n### 组件服务版本\n\n本项目的各个组件版本请移步至各个社区的 release 页面进行下载并解压运行。\n\n- [Nacos: 2.1.0 版本](https://github.com/alibaba/nacos/releases)\n- [Seata: 1.5.1 版本](https://github.com/seata/seata/releases)\n- [RocketMQ: 4.9.4 版本](https://github.com/apache/rocketmq/releases)\n- MySQL: 5.7 版本\n\n### Hosts配置\n\n为了保证代码可以正常启动，请先配置好本机的 host 映射，在配置文件中新增如下的映射。\n```shell\n# for integrated-example\n127.0.0.1 integrated-mysql\n127.0.0.1 nacos-server\n127.0.0.1 seata-server\n127.0.0.1 rocketmq\n127.0.0.1 gateway-service\n127.0.0.1 integrated-frontend\n```\n\n### 数据库配置\n\n下面开始本地环境搭建准备，在数据库配置开始之前，请确保 MySQL 的服务端开启。\n\n#### 初始化业务表\n\n针对第一个场景，订单、账户、库存微服务都需要各自的数据库，而第二个场景模拟点赞也需要存储点赞信息的数据库。\n\n运行 `spring-cloud-alibaba-examples/integrated-example/config-init/sql/init.sql` 的 sql 脚本一键创建业务所需的环境以及 Seata 相关的表。\n\n### Nacos配置\n\n至此，数据库的服务配置完毕，下面需要配置 Nacos 的配置中心有关所有的微服务配置文件。\n\n#### Nacos启动\n\n为了便于 example 的演示，这里采用 Nacos 的 `standalone` 模式启动，进入到 Nacos 解压后的目录下，执行如下命令。\n\n```shell\n#Linux/Mac环境\nsh bin/startup.sh -m standalone\n#如果您是Ubuntu环境，执行上述命令启动报错提示[[符号找不到，可以执行如下的命令\nbash bin/startup.sh -m standalone\n#Win环境\n.\\bin\\startup.cmd -m standalone\n```\n\n#### 新增配置文件\n\n在批量导入配置之前，请先修改 `spring-cloud-alibaba-examples/integrated-example/config-init/config/datasource-config.yaml` 中的数据源配置**（用户名和密码）**。\n\n之后运行 `spring-cloud-alibaba-examples/integrated-example/config-init/scripts/nacos-config-quick.sh` 来完成所有微服务配置的一键导入。\n\n```shell\n# linux\nsh nacos-config-quick.sh\n# windows 可以使用git bash来完成配置的导入 执行命令同上\n```\n\n### Seata 配置\n\nNacos 服务注册中心以及配置中心部署完毕之后，下面是 Seata 服务端的配置。\n\nSeata 的 db 模式需要额外配置数据库信息以及修改 Seata 服务端的配置文件，且在新版本中配置文件相较于旧版本进行了合并，因此这里为了便于演示方便，采用 Seata 单机的`file`模式启动 Seata Server。\n\n#### 启动 Seata Server\n\n进入到 release 解压后的 seata 目录中，执行如下命令。\n\n```shell\n#Linux/Mac环境\nsh ./bin/seata-server.sh\n#Win环境\nbin\\seata-server.bat\n```\n\n### RocketMQ 配置\n\nSeata 服务启动后可以启动 RocketMQ 的 NameServer 以及 Broker 服务。\n\n进入到 release 解压后的 rocketmq 目录中，执行如下命令。\n\n#### 启动 NameServer\n\n```shell\n#Linux/Mac环境\nsh bin/mqnamesrv\n#Win环境\n.\\bin\\mqnamesrv.cmd\n```\n\n#### 启动 Broker\n\n```shell\n#Linux/Mac环境\nsh bin/mqbroker\n#Win环境\n.\\bin\\mqbroker.cmd -n localhost:9876\n```\n\n## 运行 Demo 示例\n\n准备工作完成后可以运行 demo 示例，主要根据不同的使用场景，可以分别体验用户下单（分布式事务能力）以及模拟高流量点赞（熔断限流以及削峰填谷的能力）。\n\n首先需要分别启动 `integrated-frontend` 以及 `integrated-gateway` 微服务应用。\n\n- `integrated-gateway` 模块是整个最佳实践示例的网关。\n- `integrated-frontend` 为最佳实践示例的简易前端页面。\n\n### 分布式事务能力\n\n#### 场景说明\n\n针对分布式事务能力，SCA社区提供了**用户下单购买货物的场景**，下单后：\n\n- 先请求库存模块，扣减库存\n- 扣减账户余额\n- 生成订单信息返回响应\n\n##### 启动测试\n\n分别启动 `integrated-storage`，`integrated-account`，`integrated-order` 三个微服务应用。\n\n访问 `http://integrated-frontend:8080/order` 来体验对应场景。\n\n直接点击下单按钮提交表单，应用模拟客户端向网关发送了一个创建订单的请求。\n\n- 用户的 userId 为 admin\n- 用户下单的商品编号为1号\n- 此次订单购买的商品个数为1个\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016155416524.png)\n\n在本 demo 示例中，为了便于演示，每件商品的单价都为2。\n\n而在前面的准备工作中，**初始化业务数据库表**的时候应用新建了一个用户，用户userId 为 admin，余额为 3 元；同时新建了一个编号为 1 号的商品，库存为 100 件。\n\n因此通过上述的操作，应用会创建一个订单，扣减对应商品编号为 1 号的库存个数（100-1=99），扣减 admin 用户的余额（3-2=1）。\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016155429801.png)\n\n如果再次请求相同的接口，同样是先扣减库存（99-1=98），但是会因为 admin 用户余额不足而抛出异常，并被 Seata 捕获，执行分布式事务二阶段提交，回滚事务。\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016155436112.png)\n\n可以看到数据库中库存的记录因为回滚之后仍然为 99 件。\n\n### 熔断限流，削峰填谷能力\n\n#### 场景说明\n\n针对大流量背景下的服务熔断限流，削峰填谷，SCA社区提供了**用户为商品进行点赞的场景**。在此场景下，SCA社区提供了两种应对大流量的处理方式。\n\n- Sentinel 在网关侧绑定指定网关路由进行服务的熔断降级。\n- RocketMQ 进行流量削峰填谷，在大流量请求下，生产者向 RocketMQ 发送消息，而消费者则通过可配置的消费速率进行拉取消费，减少大流量直接请求数据库增加点赞请求的压力。\n\n#### 启动测试\n\n分别启动 `integrated-praise-provider` 以及 `integrated-praise-consumer` 模块。\n\n- Sentinel 服务熔断降级\n\n访问 `http://integrated-frontend:8080/sentinel` 体验对应场景。\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016155501290.png)\n\n网关路由点赞服务的限流规则为 5，而在前端通过异步处理模拟了 10 次并发请求。\n\n因此可以看到 Sentinel 在 Gateway 侧针对多出的流量进行了服务熔断返回 fallback 给客户端，同时数据库的点赞数进行了更新（+5）。\n\n![](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20220914155755103.png)\n\n- RocketMQ 进行流量削峰填谷\n\n访问 `http://integrated-frontend:8080/rocketmq` 体验对应场景。\n\n由于之前在 Nacos 中配置了 `integrated-praise-consumer` 消费者模块的消费速率以及间隔，在点击按钮时应用模拟 1000 个点赞请求，针对 1000 个点赞请求，`integrated-praise-provider`\n会将 1000 次请求都向 Broker 投递消息，而在消费者模块中会根据配置的消费速率进行消费，向数据库更新点赞的商品数据，模拟大流量下 RocketMQ 削峰填谷的特性。\n\n可以看到数据库中点赞的个数正在动态更新。\n\n![image-20221016173604059](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20221016173604059.png)\n\n## 其他\n\n本示例**仅是针对各个组件选取出了较为典型的功能特性来服务应用场景**\n\n当然各个组件的功能特性不仅仅只包含最佳实践中演示的这些，如果您感兴趣或是想要深入了解，欢迎学习各个组件的独立 example 相关文档。\n\n- Nacos examples\n  - [Nacos config example](../../../nacos-example/readme.md)\n  - [Nacos discovery example](../../../nacos-example/readme.md)\n- [Sentinel core example](../../../sentinel-example/README-zh.md)\n- [Seata example](../../../seata-example/readme.md)\n- [RocketMQ example](../../../rocketmq-example/readme.md)\n- "
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/docs/zh/readme-zh.md",
    "content": "# Integrated Example\n\n## 项目说明\n\n本项目为 Spring Cloud Alibaba （后文简称为 SCA）容器化部署最佳实践的 Demo 演示项目，是整合了 SCA 相关组件(Nacos, Sentinel, Seata, RocketMQ)的 Example 示例项目。\n\n主要使用的组件及及其使用特性如下：\n\n- Spring Cloud Gateway 网关\n- Nacos 配置中心和服务注册中心\n- Sentinel 熔断限流\n- Seata 分布式事务\n- RocketMQ 消息队列削峰填谷\n- Docker 微服务容器化部署\n- Kubernetes Helm Chart \n\n![整体概览](https://my-img-1.oss-cn-hangzhou.aliyuncs.com/image-20220816004541921.png)\n\n## 应用场景说明\n\n在本 demo 示例中，SCA 社区提供了两种业务场景。\n\n1) 用户下单购买货物的场景，下单后：\n\n- 先请求库存模块，扣减库存\n\n- 扣减账户余额\n\n- 生成订单信息返回响应\n\n2) 用户为商品进行点赞（模拟 MQ 的生产者消费者应用场景）返回商品点赞后的详细信息（点赞数等）。\n\n### 组件详细说明\n\n1) 其中，用户下单购买货物的场景主要使用 Seata 来进行分布式事务的能力体现。\n\n2) 用户为商品进行点赞的场景，模拟大流量环境下通过 Sentinel 进行限流或是 RocketMQ 进行削峰填谷。在此场景下，SCA社区提供了两种应对大流量的处理方式：\n\n   - Sentinel 在网关侧绑定指定网关路由进行服务的熔断降级。\n\n   - RocketMQ 进行流量削峰填谷，在大流量请求下，生产者向 RocketMQ 发送消息，而消费者则通过可配置的消费速率进行拉取消费，减少大流量直接请求数据库增加点赞请求的压力。\n\n\n#### Spring Cloud Gateway\n\n微服务模块的网关。\n\nSpring Cloud GateWay 整合 Nacos,实现动态路由配置。\n\n通过监听 Nacos 配置的改变，实现服务网关路由配置动态刷新，每次路由信息变更，无需修改配置文件而后重启服务。\n\n#### Nacos\n\n各个微服务的配置中心，服务注册中心。\n\n- 配置中心\n  - 共享配置：MySQL 数据源相关信息配置。\n\n- 注册中心\n  - 所有的微服务模块都注册到 Nacos 中进行服务注册与发现。\n  - 整合 Spring Cloud Gateway 网关。\n\n#### Seata\n\n基于 Seata 的 AT 模式，用于库存模块，账户模块，订单模块的分布式事务处理。\n\n只要库存不足/账户余额不足，回滚事务。\n\n#### Sentinel\n\n用于点赞场景的服务熔断限流。\n\n整合 Nacos 配置中心与 Spring Cloud Gateway，实现指定路由规则熔断限流规则动态配置。\n\n#### RocketMQ\n\n用于进行点赞服务流量的削峰填谷。\n\n通过将大流量的点赞请求从生产者发送到 mq，消费者模块从 mq 中拉取进行一定频率的消费，不是简单的直接服务熔断限流降级，实现 RocketMQ 针对大流量的削峰填谷能力。\n\n## 版本说明\n\n本项目提供了[本地部署运行版本](local-deployment-zh.md)、[docker-compose 版本](docker-compose-deploy-zh.md)以及 [Kubernetes Helm-Chart 版本](kubernetes-deployment-zh.md)。\n\n- 如果想要了解具体如何配置各项组件以及完整环境搭建，推荐学习[本地部署运行版本](local-deployment-zh.md)。\n\n- 如果只想运行示例代码，避免繁琐的本地环境搭建过程，又不想使用 k8s 集群。您可以尝试使用 [docker-compose 版本](docker-compose-deploy-zh.md)。\n\n- 如果想要在 K8S 集群上快速体验组件效果，跳过各个组件环境部署等过程，请查看 [Kubernetes Helm-Chart 版本](kubernetes-deployment-zh.md)。"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/helm-chart/Chart.yaml",
    "content": "apiVersion: v1\nappVersion: '1.0'\ndescription: Spring Cloud Alibaba Best Practice Example\nname: integrated-example\nversion: 1.0.0"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/helm-chart/templates/integrated-account.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: integrated-account\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: integrated-account\n  template:\n    metadata:\n      labels:\n        appName: integrated-account\n        app: integrated-account\n    spec:\n      containers:\n        - name: integrated-account\n          image: \"{{ .Values.image.repository }}integrated-account\"\n          imagePullPolicy: Always\n          ports:\n            - name: http-port\n              containerPort: 8012\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/helm-chart/templates/integrated-frontend.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  name: integrated-frontend\n  labels:\n    app: integrated-frontend\nspec:\n  type: NodePort\n  ports:\n    - port: 8080\n      name: web\n      targetPort: 8080\n      nodePort: 30080\n  selector:\n    app: integrated-frontend\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: integrated-frontend\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: integrated-frontend\n  template:\n    metadata:\n      labels:\n        appName: integrated-frontend\n        app: integrated-frontend\n    spec:\n      containers:\n        - name: integrated-frontend\n          image: \"{{ .Values.image.repository }}integrated-frontend\"\n          imagePullPolicy: Always\n          ports:\n            - name: http-port\n              containerPort: 8080\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/helm-chart/templates/integrated-gateway.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  name: gateway-service\n  labels:\n    app: integrated-gateway\nspec:\n  type: NodePort\n  ports:\n    - port: 30010\n      name: server\n      targetPort: 30010\n      nodePort: 30010\n  selector:\n    app: integrated-gateway\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: integrated-gateway\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: integrated-gateway\n  template:\n    metadata:\n      labels:\n        appName: integrated-gateway\n        app: integrated-gateway\n    spec:\n      containers:\n        - name: integrated-gateway\n          image: \"{{ .Values.image.repository }}integrated-gateway\"\n          imagePullPolicy: Always\n          ports:\n            - name: http-port\n              containerPort: 30010\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/helm-chart/templates/integrated-mysql.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  name: integrated-mysql-web\nspec:\n  ports:\n    - name: integrated-mysql-port\n      protocol: TCP\n      port: 3306\n      targetPort: 3306\n      nodePort: 30306\n  type: NodePort\n  selector:\n    app: integrated-mysql\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: integrated-mysql\n  labels:\n    app: integrated-mysql\nspec:\n  type: ClusterIP\n  ports:\n    - port: 3306\n      name: 'server'\n  selector:\n    app: integrated-mysql\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: integrated-mysql\nspec:\n  selector:\n    matchLabels:\n      app: integrated-mysql\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        app: integrated-mysql\n    spec:\n      containers:\n        - name: integrated-mysql\n          image: '{{ .Values.image.repository }}integrated-mysql'\n          imagePullPolicy: Always\n          env:\n            - name: MYSQL_ROOT_PASSWORD\n              value: '123456'\n          ports:\n            - containerPort: 3306\n              protocol: TCP"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/helm-chart/templates/integrated-nacos-mysql.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: nacos-mysql\n  labels:\n    name: nacos-mysql\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      name: nacos-mysql\n  template:\n    metadata:\n      labels:\n        name: nacos-mysql\n    spec:\n      containers:\n        - name: mysql\n          image: registry.cn-hangzhou.aliyuncs.com/sca-community/integrated-nacos-mysql\n          ports:\n            - containerPort: 3306\n          env:\n            - name: MYSQL_ROOT_PASSWORD\n              value: 'root'\n            - name: MYSQL_DATABASE\n              value: 'nacos_config'\n            - name: MYSQL_USER\n              value: 'nacos'\n            - name: MYSQL_PASSWORD\n              value: 'nacos'\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: nacos-mysql\n  labels:\n    name: nacos-mysql\nspec:\n  ports:\n    - port: 3307\n      targetPort: 3306\n  selector:\n    name: nacos-mysql\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: nacos-mysql-web\nspec:\n  ports:\n    - name: nacos-mysql-port\n      protocol: TCP\n      port: 3307\n      targetPort: 3306\n      nodePort: 30307\n  type: NodePort\n  selector:\n    name: nacos-mysql"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/helm-chart/templates/integrated-nacos-stand.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  name: nacos-svc\n  labels:\n    app: nacos-svc\nspec:\n  type: NodePort\n  ports:\n    - port: 8848\n      name: server\n      targetPort: 8848\n      nodePort: 30848\n  selector:\n    app: nacos-standalone\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: nacos-server\n  labels:\n    app: nacos-server\nspec:\n  type: ClusterIP\n  ports:\n    - port: 8848\n      name: server\n      targetPort: 8848\n    - port: 9848\n      name: client-rpc\n      targetPort: 9848\n    - port: 9849\n      name: raft-rpc\n      targetPort: 9849\n    - port: 7848\n      name: old-raft-rpc\n      targetPort: 7848\n  selector:\n    app: nacos-standalone\n---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: nacos-cm\ndata:\n  mysql.host: \"nacos-mysql\"\n  mysql.db.name: \"nacos_config\"\n  mysql.port: \"3307\"\n  mysql.user: \"nacos\"\n  mysql.password: \"nacos\"\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: nacos-standalone\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        app: nacos-standalone\n      annotations:\n        pod.alpha.kubernetes.io/initialized: \"true\"\n    spec:\n      affinity:\n        podAntiAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            - labelSelector:\n                matchExpressions:\n                  - key: \"app\"\n                    operator: In\n                    values:\n                      - nacos-standalone\n              topologyKey: \"kubernetes.io/hostname\"\n      containers:\n        - name: local-nacos\n          imagePullPolicy: Always\n          image: registry.cn-hangzhou.aliyuncs.com/sca-community/nacos-server\n          ports:\n            - containerPort: 8848\n              name: client\n            - containerPort: 9848\n              name: client-rpc\n            - containerPort: 9849\n              name: raft-rpc\n            - containerPort: 7848\n              name: old-raft-rpc\n          env:\n            - name: SPRING_DATASOURCE_PLATFORM\n              value: \"mysql\"\n            - name: MYSQL_SERVICE_HOST\n              valueFrom:\n                configMapKeyRef:\n                  name: nacos-cm\n                  key: mysql.host\n            - name: MYSQL_SERVICE_DB_NAME\n              valueFrom:\n                configMapKeyRef:\n                  name: nacos-cm\n                  key: mysql.db.name\n            - name: MYSQL_SERVICE_PORT\n              valueFrom:\n                configMapKeyRef:\n                  name: nacos-cm\n                  key: mysql.port\n            - name: MYSQL_SERVICE_USER\n              valueFrom:\n                configMapKeyRef:\n                  name: nacos-cm\n                  key: mysql.user\n            - name: MYSQL_SERVICE_PASSWORD\n              valueFrom:\n                configMapKeyRef:\n                  name: nacos-cm\n                  key: mysql.password\n            - name: MODE\n              value: \"standalone\"\n            - name: NACOS_SERVER_PORT\n              value: \"8848\"\n            - name: PREFER_HOST_MODE\n              value: \"hostname\"\n  selector:\n    matchLabels:\n      app: nacos-standalone\n\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/helm-chart/templates/integrated-order.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: integrated-order\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: integrated-order\n  template:\n    metadata:\n      labels:\n        appName: integrated-order\n        app: integrated-order\n    spec:\n      containers:\n        - name: integrated-order\n          image: \"{{ .Values.image.repository }}integrated-order\"\n          imagePullPolicy: Always\n          ports:\n            - name: http-port\n              containerPort: 8013\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/helm-chart/templates/integrated-praise-consumer.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: integrated-praise-consumer\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: integrated-praise-consumer\n  template:\n    metadata:\n      labels:\n        appName: integrated-praise-consumer\n        app: integrated-praise-consumer\n    spec:\n      containers:\n        - name: integrated-praise-consumer\n          image: \"{{ .Values.image.repository }}integrated-praise-consumer\"\n          imagePullPolicy: Always\n          ports:\n            - name: http-port\n              containerPort: 8014\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/helm-chart/templates/integrated-praise-provider.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: integrated-praise-provider\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: integrated-praise-provider\n  template:\n    metadata:\n      labels:\n        appName: integrated-praise-provider\n        app: integrated-praise-provider\n    spec:\n      containers:\n        - name: integrated-praise-provider\n          image: \"{{ .Values.image.repository }}integrated-praise-provider\"\n          imagePullPolicy: Always\n          ports:\n            - name: http-port\n              containerPort: 8015\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/helm-chart/templates/integrated-rocketmq.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  name: rocketmq\nspec:\n  ports:\n    - port: 9876\n      protocol: TCP\n      targetPort: 9876\n  selector:\n    app: mqnamesrv\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n  name: mqnamesrv\nspec:\n  serviceName: mqnamesrv\n  replicas: 1\n  selector:\n    matchLabels:\n      app: mqnamesrv\n  template:\n    metadata:\n      labels:\n        app: mqnamesrv\n    spec:\n      containers:\n        - name: mqnamesrv\n          image: registry.cn-hangzhou.aliyuncs.com/sca-community/rocketmq-server\n          command: [\"sh\",\"/usr/local/rocketmq-4.8.0/bin/mqnamesrv\"]\n          imagePullPolicy: IfNotPresent\n          ports:\n            - containerPort: 9876\n              protocol: TCP\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n  name: mqbroker\nspec:\n  serviceName: mqbroker\n  replicas: 1\n  selector:\n    matchLabels:\n      app: mqbroker\n  template:\n    metadata:\n      labels:\n        app: mqbroker\n    spec:\n      containers:\n        - name: mqbroker\n          image: registry.cn-hangzhou.aliyuncs.com/sca-community/rocketmq-server\n          command: [\"sh\",\"/usr/local/rocketmq-4.8.0/bin/mqbroker\", \"-n\",\"rocketmq:9876\"]\n          imagePullPolicy: IfNotPresent\n          env:\n            - name: JAVA_OPT\n              value: \"-server -XX:ParallelGCThreads=1 -Xms1g -Xmx1g -Xmn512m\"\n          ports:\n            - containerPort: 10909\n            - containerPort: 10911\n          resources:\n            requests:\n              memory: 128Mi"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/helm-chart/templates/integrated-seata.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  name: seata-server\n  labels:\n    k8s-app: seata-server\nspec:\n  type: ClusterIP\n  ports:\n    - port: 8091\n      name: server\n  selector:\n    k8s-app: seata-server\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: seata-server\n  labels:\n    k8s-app: seata-server\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      k8s-app: seata-server\n  template:\n    metadata:\n      labels:\n        k8s-app: seata-server\n    spec:\n      containers:\n        - name: seata-server\n          image: registry.cn-hangzhou.aliyuncs.com/sca-community/seata-server\n          imagePullPolicy: IfNotPresent\n          env:\n            - name: SEATA_PORT\n              value: '8091'\n            - name: STORE_MODE\n              value: file\n          ports:\n            - name: http\n              containerPort: 8091\n              protocol: TCP"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/helm-chart/templates/integrated-storage.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: integrated-storage\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: integrated-storage\n  template:\n    metadata:\n      labels:\n        appName: integrated-storage\n        app: integrated-storage\n    spec:\n      containers:\n        - name: integrated-storage\n          image: '{{ .Values.image.repository }}integrated-storage'\n          imagePullPolicy: Always\n          ports:\n            - name: http-port\n              containerPort: 8011\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/helm-chart/values.yaml",
    "content": "image:\n  repository: registry.cn-hangzhou.aliyuncs.com/sca-community/"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-account/Dockerfile",
    "content": "FROM openjdk:8-jdk-alpine as builder\n\nLABEL author=\"yuluo\" \\\n\temail=\"yuluo829@aliyun.com\"\n\nADD ./integrated-account/target/integrated-account-*.jar /app.jar\n\nRUN sh -c 'touch /app.jar'\nEXPOSE 8012\n\nENTRYPOINT [\"java\", \"-jar\",\"/app.jar\"]"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-account/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n\t\t xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\t\t xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<parent>\n\t\t<artifactId>spring-cloud-alibaba-examples</artifactId>\n\t\t<groupId>com.alibaba.cloud</groupId>\n\t\t<version>${revision}</version>\n\t\t<relativePath>../../pom.xml</relativePath>\n\t</parent>\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<artifactId>integrated-account</artifactId>\n\t<name>Spring Cloud Alibaba Integrated Account Example</name>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-jdbc</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.mysql</groupId>\n\t\t\t<artifactId>mysql-connector-j</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba</groupId>\n\t\t\t<artifactId>druid-spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.mybatis.spring.boot</groupId>\n\t\t\t<artifactId>mybatis-spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-alibaba-seata</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba.cloud</groupId>\n\t\t\t<artifactId>integrated-common</artifactId>\n\t\t\t<version>${revision}</version>\n\t\t</dependency>\n\t</dependencies>\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-account/src/main/java/com/alibaba/cloud/integration/account/AccountServiceApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.account;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * @author TrevorLink\n */\n@SpringBootApplication\npublic class AccountServiceApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(AccountServiceApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-account/src/main/java/com/alibaba/cloud/integration/account/controller/AccountController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.account.controller;\n\nimport com.alibaba.cloud.integration.account.dto.AccountDTO;\nimport com.alibaba.cloud.integration.account.service.AccountService;\nimport com.alibaba.cloud.integration.common.BusinessException;\nimport com.alibaba.cloud.integration.common.Result;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author TrevorLink\n */\n@RestController\n@RequestMapping(\"/account\")\npublic class AccountController {\n\n\t@Autowired\n\tprivate AccountService accountService;\n\n\t@PostMapping(\"/reduce-balance\")\n\tpublic Result<?> reduceBalance(@RequestBody AccountDTO accountDTO) {\n\t\ttry {\n\t\t\taccountService.reduceBalance(accountDTO.getUserId(), accountDTO.getPrice());\n\t\t}\n\t\tcatch (BusinessException e) {\n\t\t\treturn Result.failed(e.getMessage());\n\t\t}\n\t\treturn Result.success(\"\");\n\t}\n\n\t@GetMapping(\"/\")\n\tpublic Result<?> getRemainAccount(String userId) {\n\t\treturn accountService.getRemainAccount(userId);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-account/src/main/java/com/alibaba/cloud/integration/account/dto/AccountDTO.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.account.dto;\n\n/**\n * @author TrevorLink\n */\npublic class AccountDTO {\n\n\tprivate String userId;\n\n\tprivate Integer price;\n\n\tpublic String getUserId() {\n\t\treturn userId;\n\t}\n\n\tpublic void setUserId(String userId) {\n\t\tthis.userId = userId;\n\t}\n\n\tpublic Integer getPrice() {\n\t\treturn price;\n\t}\n\n\tpublic void setPrice(Integer price) {\n\t\tthis.price = price;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-account/src/main/java/com/alibaba/cloud/integration/account/mapper/AccountMapper.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.account.mapper;\n\nimport java.sql.Timestamp;\n\nimport org.apache.ibatis.annotations.Mapper;\nimport org.apache.ibatis.annotations.Param;\nimport org.apache.ibatis.annotations.Select;\nimport org.apache.ibatis.annotations.Update;\n\nimport org.springframework.stereotype.Repository;\n\n/**\n * @author TrevorLink\n */\n@Mapper\n@Repository\npublic interface AccountMapper {\n\n\t@Select(\"SELECT money FROM account WHERE user_id = #{userId}\")\n\tInteger getBalance(@Param(\"userId\") String userId);\n\n\t@Update(\"UPDATE account SET money = money - #{price},update_time = #{updateTime} WHERE user_id = #{userId} AND money >= ${price}\")\n\tint reduceBalance(@Param(\"userId\") String userId, @Param(\"price\") Integer price,\n\t\t\t@Param(\"updateTime\") Timestamp updateTime);\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-account/src/main/java/com/alibaba/cloud/integration/account/service/AccountService.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.account.service;\n\nimport com.alibaba.cloud.integration.common.BusinessException;\nimport com.alibaba.cloud.integration.common.Result;\n\n/**\n * @author TrevorLink\n */\npublic interface AccountService {\n\n\tvoid reduceBalance(String userId, Integer price) throws BusinessException;\n\n\tResult<?> getRemainAccount(String userId);\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-account/src/main/java/com/alibaba/cloud/integration/account/service/impl/AccountServiceImpl.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.account.service.impl;\n\nimport java.sql.Timestamp;\n\nimport com.alibaba.cloud.integration.account.mapper.AccountMapper;\nimport com.alibaba.cloud.integration.account.service.AccountService;\nimport com.alibaba.cloud.integration.common.BusinessException;\nimport com.alibaba.cloud.integration.common.Result;\nimport org.apache.seata.core.context.RootContext;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n/**\n * @author TrevorLink\n */\n@Service\npublic class AccountServiceImpl implements AccountService {\n\n\tprivate Logger logger = LoggerFactory.getLogger(getClass());\n\n\t@Autowired\n\tprivate AccountMapper accountMapper;\n\n\t@Override\n\t@Transactional\n\tpublic void reduceBalance(String userId, Integer price) throws BusinessException {\n\t\tlogger.info(\"[reduceBalance] currenet XID: {}\", RootContext.getXID());\n\n\t\tcheckBalance(userId, price);\n\n\t\tTimestamp updateTime = new Timestamp(System.currentTimeMillis());\n\t\tint updateCount = accountMapper.reduceBalance(userId, price, updateTime);\n\t\tif (updateCount == 0) {\n\t\t\tthrow new BusinessException(\"reduce balance failed\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic Result<?> getRemainAccount(String userId) {\n\t\tInteger balance = accountMapper.getBalance(userId);\n\t\tif (balance == null) {\n\t\t\treturn Result.failed(\"wrong userId,please check the userId\");\n\t\t}\n\t\treturn Result.success(balance);\n\t}\n\n\tprivate void checkBalance(String userId, Integer price) throws BusinessException {\n\t\tInteger balance = accountMapper.getBalance(userId);\n\t\tif (balance < price) {\n\t\t\tthrow new BusinessException(\"no enough balance\");\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-account/src/main/resources/application.yaml",
    "content": "server:\n  port: 8012\n\nspring:\n  application:\n    name: integrated-account\n  cloud:\n    nacos:\n      discovery:\n        server-addr: nacos-server:8848\n        group: integrated-example\n      config:\n        server-addr: nacos-server:8848\n        group: integrated-example\n        file-extension: yaml\n  config:\n    import:\n      - optional:nacos:integrated-account.yaml\n      - optional:nacos:datasource-config.yaml\n\nseata:\n  application-id: ${spring.application.name}\n  tx-service-group: ${spring.application.name}-group\n  service:\n    vgroup-mapping:\n      integrated-account-group: default\n    grouplist:\n      default: seata-server:8091\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-common/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <groupId>com.alibaba.cloud</groupId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>integrated-common</artifactId>\n    <name>Spring Cloud Alibaba Integrated Common Example</name>\n\n</project>"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-common/src/main/java/com/alibaba/cloud/integration/common/BusinessException.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.common;\n\n/**\n * @author TrevorLink\n */\npublic class BusinessException extends RuntimeException {\n\n\tpublic BusinessException(String message) {\n\t\tsuper(message);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-common/src/main/java/com/alibaba/cloud/integration/common/IResult.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.common;\n\npublic interface IResult {\n\n\t/**\n\t * Get result code.\n\t * @return result code\n\t */\n\tInteger getCode();\n\n\t/**\n\t * Get result message.\n\t * @return result message\n\t */\n\tString getMessage();\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-common/src/main/java/com/alibaba/cloud/integration/common/Result.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.common;\n\n/**\n * @author TrevorLink\n */\npublic class Result<T> {\n\n\tprivate Integer code;\n\n\tprivate String message;\n\n\tprivate T data;\n\n\tpublic static <T> Result<T> success(T data) {\n\t\treturn new Result<>(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMessage(),\n\t\t\t\tdata);\n\t}\n\n\tpublic static <T> Result<T> success(String message, T data) {\n\t\treturn new Result<>(ResultEnum.SUCCESS.getCode(), message, data);\n\t}\n\n\tpublic static Result<?> failed() {\n\t\treturn new Result<>(ResultEnum.COMMON_FAILED.getCode(),\n\t\t\t\tResultEnum.COMMON_FAILED.getMessage(), null);\n\t}\n\n\tpublic static Result<?> failed(String message) {\n\t\treturn new Result<>(ResultEnum.COMMON_FAILED.getCode(), message, null);\n\t}\n\n\tpublic static Result<?> failed(IResult errorResult) {\n\t\treturn new Result<>(errorResult.getCode(), errorResult.getMessage(), null);\n\t}\n\n\tpublic Result() {\n\t}\n\n\tpublic Result(Integer code, String message, T data) {\n\t\tthis.code = code;\n\t\tthis.message = message;\n\t\tthis.data = data;\n\t}\n\n\tpublic Integer getCode() {\n\t\treturn code;\n\t}\n\n\tpublic void setCode(Integer code) {\n\t\tthis.code = code;\n\t}\n\n\tpublic String getMessage() {\n\t\treturn message;\n\t}\n\n\tpublic void setMessage(String message) {\n\t\tthis.message = message;\n\t}\n\n\tpublic T getData() {\n\t\treturn data;\n\t}\n\n\tpublic void setData(T data) {\n\t\tthis.data = data;\n\t}\n\n\tpublic static <T> Result<T> instance(Integer code, String message, T data) {\n\t\tResult<T> result = new Result<>();\n\t\tresult.setCode(code);\n\t\tresult.setMessage(message);\n\t\tresult.setData(data);\n\t\treturn result;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-common/src/main/java/com/alibaba/cloud/integration/common/ResultEnum.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.common;\n\n/**\n * Integrated Example common result enum class.\n * @author TrevorLink\n */\npublic enum ResultEnum implements IResult {\n\n\t/**\n\t * return success result.\n\t */\n\tSUCCESS(2001, \"接口调用成功\"),\n\t/**\n\t * return business common failed.\n\t */\n\tCOMMON_FAILED(2003, \"接口调用失败\");\n\n\tprivate Integer code;\n\n\tprivate String message;\n\n\tResultEnum() {\n\t}\n\n\tResultEnum(Integer code, String message) {\n\t\tthis.code = code;\n\t\tthis.message = message;\n\t}\n\n\t@Override\n\tpublic Integer getCode() {\n\t\treturn code;\n\t}\n\n\tpublic void setCode(Integer code) {\n\t\tthis.code = code;\n\t}\n\n\t@Override\n\tpublic String getMessage() {\n\t\treturn message;\n\t}\n\n\tpublic void setMessage(String message) {\n\t\tthis.message = message;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-frontend/Dockerfile",
    "content": "FROM openjdk:8-jdk-alpine as builder\n\nLABEL author=\"yuluo\" \\\n\temail=\"yuluo829@aliyun.com\"\n\nADD ./integrated-frontend/target/integrated-frontend-*.jar /app.jar\n\nRUN sh -c 'touch /app.jar'\n\nEXPOSE 8080\n\nENTRYPOINT [\"java\", \"-jar\", \"/app.jar\"]\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-frontend/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n\t\t xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\t\t xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<parent>\n\t\t<artifactId>spring-cloud-alibaba-examples</artifactId>\n\t\t<groupId>com.alibaba.cloud</groupId>\n\t\t<version>${revision}</version>\n\t\t<relativePath>../../pom.xml</relativePath>\n\t</parent>\n\t<modelVersion>4.0.0</modelVersion>\n\t<packaging>jar</packaging>\n\t<artifactId>integrated-frontend</artifactId>\n\t<name>Spring Cloud Alibaba Integrated Frontend Example</name>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-thymeleaf</artifactId>\n\t\t</dependency>\n\t</dependencies>\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-frontend/src/main/java/com/alibaba/cloud/integration/frontend/FrontendApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.frontend;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * @author HuangSir\n * @date 2022-09-08 14:11\n */\n@SpringBootApplication\npublic class FrontendApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(FrontendApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-frontend/src/main/java/com/alibaba/cloud/integration/frontend/controller/IntegrationController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.frontend.controller;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\n\n/**\n * @author HuangSir\n * @date 2022-09-08 14:00\n */\n@Controller\npublic class IntegrationController {\n\n\t@RequestMapping(\"/order\")\n\tpublic String order() {\n\t\treturn \"order\";\n\t}\n\n\t@RequestMapping(\"/rocketmq\")\n\tpublic String rocketmq() {\n\t\treturn \"rocketmq\";\n\t}\n\n\t@RequestMapping(\"/sentinel\")\n\tpublic String sentinel() {\n\t\treturn \"sentinel\";\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-frontend/src/main/resources/templates/order.html",
    "content": "<!DOCTYPE HTML>\n<html xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<head>\n    <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n    <title></title>\n    <script src=\"https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js\"></script>\n</head>\n<body th:style=\"${'background-color:' + backgroundColor }\">\n<div style=\"margin: 30px auto 0 30px;\">\n    <div id=\"orderSection\">\n        <label>商品下单场景：</label>\n        <form id=\"orderForm\">\n            <div>\n                <label>用户ID</label>\n                <input type=\"text\" id=\"userId\" name=\"userId\" value=\"admin\"/>\n            </div>\n            <div>\n                <label>商品编号</label>\n                <input type=\"text\" id=\"commodityCode\" name=\"commodityCode\" value=\"1\"/>\n            </div>\n            <div>\n                <label>商品个数</label>\n                <input type=\"number\" name=\"count\" value=\"1\"/>\n            </div>\n            <button type=\"button\" class=\"btnStart\">提交</button>\n        </form>\n    </div>\n    <div id=\"orderResultSection\" style=\"margin-top: 30px; border-top: 1px solid #eaeaea;\">\n    </div>\n</div>\n<script charset=\"utf-8\">\n    $(\".btnStart\").click(function () {\n        $('#orderResultSection').empty();\n        var userId = $(\"#userId\").val();\n        var commodityCode = $(\"#commodityCode\").val();\n        $.ajax({\n            url: \"http://gateway-service:30010/storage/\",\n            type: \"get\",\n            dataType: \"json\",\n            data: \"commodityCode=\" + commodityCode,\n            async:false,\n            success: function (res) {\n                $('#orderResultSection').append(`<p> [${getDateTime()}] 执行分布式业务前商品库存： ${res.data} </p>`);\n            }\n        });\n        $.ajax({\n            url: \"http://gateway-service:30010/account/\",\n            type: \"get\",\n            dataType: \"json\",\n            data: \"userId=\" + userId,\n            async:false,\n            success: function (res) {\n                $('#orderResultSection').append(`<p> [${getDateTime()}] 执行分布式业务前账户余额： ${res.data}</p>`);\n            }\n        });\n        $.ajax({\n            type: \"POST\",\n            url: \"http://gateway-service:30010/order/create\",\n            data: $('#orderForm').serialize(),\n            dataType: 'json',\n            async:false,\n            success: function (res) {\n                $('#orderResultSection').append(`<p> [${getDateTime()}] ${res.message} </p>`);\n                $.ajax({\n                    url: \"http://gateway-service:30010/storage/\",\n                    type: \"get\",\n                    dataType: \"json\",\n                    data: \"commodityCode=\" + commodityCode,\n                    async:false,\n                    success: function (res) {\n                        $('#orderResultSection').append(`<p> [${getDateTime()}] 执行分布式业务后商品库存： ${res.data}</p>`);\n                    }\n                });\n                $.ajax({\n                    url: \"http://gateway-service:30010/account/\",\n                    type: \"get\",\n                    dataType: \"json\",\n                    data: \"userId=\" + userId,\n                    async:false,\n                    success: function (res) {\n                        $('#orderResultSection').append(`<p> [${getDateTime()}] 执行分布式业务后账户余额： ${res.data}</p>`);\n                    }\n                });\n            }\n        });\n    });\n    const getDateTime = () => {\n        const myDate = new Date;\n        const year = myDate.getFullYear();\n        const month = myDate.getMonth() + 1;\n        const date = myDate.getDate();\n        const hours = myDate.getHours();\n        const minutes = myDate.getMinutes();\n        const seconds = myDate.getSeconds();\n        return `${year}-${month}-${date} ${hours}:${minutes}:${seconds}`;\n    };\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-frontend/src/main/resources/templates/rocketmq.html",
    "content": "<!DOCTYPE HTML>\n<html xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<head>\n    <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n    <title></title>\n    <script src=\"https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js\"></script>\n</head>\n<body th:style=\"${'background-color:' + backgroundColor }\">\n<div style=\"margin: 30px auto 0 30px;\">\n    <div id=\"RocketMQSection\">\n        <label>RocketMQ 削峰填谷场景：</label>\n        <br>\n        <label>被点赞的商品ID</label>\n        <input id=\"itemId\" style=\"width: 200px;height: 20px;\" value=\"1\">\n        <br>\n        <button class=\"btnStart\">开始调用</button>\n    </div>\n    <div id=\"rocketmqResultSection\" style=\"margin-top: 30px; border-top: 1px solid #eaeaea;\">\n    </div>\n</div>\n<script charset=\"utf-8\">\n    var count = 0;\n    window.onload = function () {\n        const timeId = setInterval(function () {\n            if (count == 1000) {\n                console.log(\"终止轮询\")\n                clearInterval(timeId)\n            }\n            queryRes()\n        }, 500)\n\n        function queryRes() {\n            $.ajax({\n                url: \"http://gateway-service:30010/praise/query\",\n                type: \"get\",\n                dataType: \"json\",\n                data: \"itemId=\" + $('#itemId').val(),\n                success: function (res) {\n                    console.log(\"准备查询，此时count=\" + count)\n                    $('#rocketmqResultSection').append(`<p> [${getDateTime()}] 点赞数： ${res} </p>`);\n                }\n            })\n        }\n    }\n    $('.btnStart').click(() => {\n        var itemId = $('#itemId').val();\n        $('#rocketmqResultSection').empty();\n\n        for (let i = 0; i < 1000; i++) {\n            $.ajax({\n                url: \"http://gateway-service:30010/praise/rocketmq\",\n                type: \"get\",\n                dataType: \"json\",\n                data: \"itemId=\" + itemId,\n                success: function () {\n                    console.log(\"点赞成功，更新count\")\n                    count++;\n                }\n            });\n        }\n\n    });\n\n    const getDateTime = () => {\n        const myDate = new Date;\n        const year = myDate.getFullYear();\n        const month = myDate.getMonth() + 1;\n        const date = myDate.getDate();\n        const hours = myDate.getHours();\n        const minutes = myDate.getMinutes();\n        const seconds = myDate.getSeconds();\n        return `${year}-${month}-${date} ${hours}:${minutes}:${seconds}`;\n    };\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-frontend/src/main/resources/templates/sentinel.html",
    "content": "<!DOCTYPE HTML>\n<html xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<head>\n    <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n    <title></title>\n    <script src=\"https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js\"></script>\n</head>\n<body th:style=\"${'background-color:' + backgroundColor }\">\n<div style=\"margin: 30px auto 0 30px;\">\n    <div id=\"SentinelSection\">\n        <label>Sentinel 限流降级场景：</label>\n        <br>\n        <label>被点赞的商品ID</label>\n        <input id=\"itemId\" style=\"width: 200px;height: 20px;\" value=\"1\">\n        <br>\n        <button class=\"btnStart\">开始调用</button>\n    </div>\n    <div id=\"sentinelResultSection\" style=\"margin-top: 30px; border-top: 1px solid #eaeaea;\">\n    </div>\n</div>\n<script charset=\"utf-8\">\n    $('.btnStart').click(() => {\n        $('#sentinelResultSection').empty();\n        var itemId = $('#itemId').val();\n        $.ajax({\n            url: \"http://gateway-service:30010/praise/query\",\n            type: \"get\",\n            dataType: \"json\",\n            data: \"itemId=\" + itemId,\n            async: false,\n            success: function (res) {\n                $('#sentinelResultSection').append(`<p> [${getDateTime()}] 点赞前的点赞数： ${res} </p>`);\n            }\n        });\n        for (let i = 0; i < 10; i++) {\n            $.ajax({\n                url: \"http://gateway-service:30010/praise/sentinel\",\n                type: \"get\",\n                dataType: \"json\",\n                data: \"itemId=\" + itemId,\n                success: function (res) {\n                    console.log(res)\n                    $('#sentinelResultSection').append(`<p> [${getDateTime()}] ${getDateTime()}: ${res}</p>`);\n                },\n                error: function (res) {\n                    console.log(res)\n                    $('#sentinelResultSection').append(`<p> [${getDateTime()}]: 请求失败，接口被限流 </p>`);\n                }\n            });\n        }\n        timeoutid = setTimeout(queryRes, 1000);\n        function queryRes() {\n            $.ajax({\n                url: \"http://gateway-service:30010/praise/query\",\n                type: \"get\",\n                dataType: \"json\",\n                data: \"itemId=\" + $('#itemId').val(),\n                success: function (res) {\n                    $('#sentinelResultSection').append(`<p> [${getDateTime()}] 点赞后的点赞数： ${res} </p>`);\n                }\n            })\n        }\n\n    });\n\n\n    const getDateTime = () => {\n        const myDate = new Date;\n        const year = myDate.getFullYear(); //获取当前年\n        const month = myDate.getMonth() + 1; //获取当前月\n        const date = myDate.getDate(); //获取当前日\n        const hours = myDate.getHours();\n        const minutes = myDate.getMinutes();\n        const seconds = myDate.getSeconds();\n        return `${year}-${month}-${date} ${hours}:${minutes}:${seconds}`;\n    };\n</script>\n</body>\n</html>"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-gateway/Dockerfile",
    "content": "FROM openjdk:8-jdk-alpine as builder\n\nLABEL author=\"yuluo\" \\\n\temail=\"yuluo829@aliyun.com\"\n\nADD ./integrated-gateway/target/integrated-gateway-*.jar /app.jar\n\nRUN sh -c 'touch /app.jar'\nEXPOSE 30010\n\nENTRYPOINT [\"java\", \"-jar\",\"/app.jar\"]"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-gateway/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n\t\t xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\t\t xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<parent>\n\t\t<artifactId>spring-cloud-alibaba-examples</artifactId>\n\t\t<groupId>com.alibaba.cloud</groupId>\n\t\t<version>${revision}</version>\n\t\t<relativePath>../../pom.xml</relativePath>\n\t</parent>\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<artifactId>integrated-gateway</artifactId>\n\t<name>Spring Cloud Alibaba Integrated Gateway Example</name>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-gateway-server-webflux</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t\t<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-loadbalancer</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba.csp</groupId>\n\t\t\t<artifactId>sentinel-spring-cloud-gateway-v6x-adapter</artifactId>\n\t\t</dependency>\n\t</dependencies>\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-gateway/src/main/java/com/alibaba/cloud/integration/gateway/GatewayApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.gateway;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\n\n/**\n * @author TrevorLink\n */\n@SpringBootApplication\n@EnableDiscoveryClient\npublic class GatewayApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(GatewayApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-gateway/src/main/java/com/alibaba/cloud/integration/gateway/config/GatewayConfig.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.gateway.config;\n\nimport java.nio.charset.StandardCharsets;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\n\nimport com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;\nimport com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;\nimport com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;\nimport com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;\nimport com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;\nimport com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;\nimport jakarta.annotation.PostConstruct;\nimport reactor.core.publisher.Mono;\n\nimport org.springframework.beans.factory.ObjectProvider;\nimport org.springframework.cloud.gateway.filter.GlobalFilter;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.Ordered;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.codec.ServerCodecConfigurer;\nimport org.springframework.web.cors.CorsConfiguration;\nimport org.springframework.web.cors.reactive.CorsWebFilter;\nimport org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;\nimport org.springframework.web.reactive.function.BodyInserters;\nimport org.springframework.web.reactive.function.server.ServerResponse;\nimport org.springframework.web.reactive.result.view.ViewResolver;\nimport org.springframework.web.server.ServerWebExchange;\n\n/**\n * @author TrevorLink\n */\n@Configuration\npublic class GatewayConfig {\n\n\tprivate final List<ViewResolver> viewResolvers;\n\n\tprivate final ServerCodecConfigurer serverCodecConfigurer;\n\n\tpublic GatewayConfig(ObjectProvider<List<ViewResolver>> viewResolversProvider,\n\t\t\tServerCodecConfigurer serverCodecConfigurer) {\n\t\tthis.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);\n\t\tthis.serverCodecConfigurer = serverCodecConfigurer;\n\t}\n\n\t@Bean\n\t@Order(Ordered.HIGHEST_PRECEDENCE)\n\tpublic GlobalFilter sentinelGatewayFilter() {\n\t\treturn new SentinelGatewayFilter();\n\t}\n\n\t@PostConstruct\n\tpublic void initGatewayRules() {\n\t\tSet<GatewayFlowRule> rules = new HashSet<>();\n\t\trules.add(\n\t\t\t\tnew GatewayFlowRule(\"praiseItemSentinel\").setCount(5).setIntervalSec(1));\n\t\tGatewayRuleManager.loadRules(rules);\n\t}\n\n\t@Bean\n\t@Order(Ordered.HIGHEST_PRECEDENCE)\n\tpublic SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {\n\t\t// Register the block exception handler for Spring Cloud Gateway.\n\t\treturn new SentinelGatewayBlockExceptionHandler(viewResolvers,\n\t\t\t\tserverCodecConfigurer);\n\t}\n\n\t@PostConstruct\n\tpublic void initBlockHandlers() {\n\t\tBlockRequestHandler blockRequestHandler = new BlockRequestHandler() {\n\t\t\t@Override\n\t\t\tpublic Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange,\n\t\t\t\t\tThrowable throwable) {\n\t\t\t\treturn ServerResponse.status(HttpStatus.OK)\n\t\t\t\t\t\t.contentType(new MediaType(\"application\", \"json\", StandardCharsets.UTF_8))\n\t\t\t\t\t\t.body(BodyInserters.fromValue(\"此接口被限流了\"));\n\t\t\t}\n\t\t};\n\t\tGatewayCallbackManager.setBlockHandler(blockRequestHandler);\n\t}\n\n\t@Bean\n\tpublic CorsWebFilter corsFilter() {\n\t\tUrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();\n\t\tCorsConfiguration config = new CorsConfiguration();\n\t\tconfig.setAllowCredentials(true);\n\t\tconfig.addAllowedHeader(\"*\");\n\t\tconfig.addAllowedMethod(\"*\");\n\t\tconfig.addAllowedOriginPattern(\"*\");\n\t\tsource.registerCorsConfiguration(\"/**\", config);\n\n\t\treturn new CorsWebFilter(source);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-gateway/src/main/resources/application.yaml",
    "content": "server:\n  port: 30010\nspring:\n  application:\n    name: integrated-gateway\n  cloud:\n    nacos:\n      config:\n        server-addr: nacos-server:8848\n        group: integrated-example\n        file-extension: yaml\n      discovery:\n        server-addr: nacos-server:8848\n        group: integrated-example\n  config:\n    import: optional:nacos:integrated-gateway.yaml\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-order/Dockerfile",
    "content": "FROM openjdk:8-jdk-alpine as builder\n\nLABEL author=\"yuluo\" \\\n\temail=\"yuluo829@aliyun.com\"\n\nADD ./integrated-order/target/integrated-order-*.jar /app.jar\n\nRUN sh -c 'touch /app.jar'\nEXPOSE 8013\n\nENTRYPOINT [\"java\", \"-jar\",\"/app.jar\"]"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-order/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <groupId>com.alibaba.cloud</groupId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>integrated-order</artifactId>\n    <name>Spring Cloud Alibaba Integrated Order Example</name>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-jdbc</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.mysql</groupId>\n            <artifactId>mysql-connector-j</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>druid-spring-boot-starter</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.mybatis.spring.boot</groupId>\n            <artifactId>mybatis-spring-boot-starter</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-openfeign</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-loadbalancer</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>integrated-common</artifactId>\n            <version>${revision}</version>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-order/src/main/java/com/alibaba/cloud/integration/order/OrderServiceApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.order;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.openfeign.EnableFeignClients;\n\n/**\n * @author TrevorLink\n */\n@SpringBootApplication\n@EnableFeignClients\npublic class OrderServiceApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(OrderServiceApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-order/src/main/java/com/alibaba/cloud/integration/order/controller/OrderController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.order.controller;\n\nimport com.alibaba.cloud.integration.common.BusinessException;\nimport com.alibaba.cloud.integration.common.Result;\nimport com.alibaba.cloud.integration.order.service.OrderService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author TrevorLink\n */\n@RestController\n@RequestMapping(\"/order\")\npublic class OrderController {\n\n\t@Autowired\n\tprivate OrderService orderService;\n\n\t@PostMapping(\"/create\")\n\tpublic Result<?> createOrder(@RequestParam(\"userId\") String userId,\n\t\t\t@RequestParam(\"commodityCode\") String commodityCode,\n\t\t\t@RequestParam(\"count\") Integer count) {\n\t\tResult<?> res = null;\n\t\ttry {\n\t\t\tres = orderService.createOrder(userId, commodityCode, count);\n\t\t}\n\t\tcatch (BusinessException e) {\n\t\t\treturn Result.failed(e.getMessage());\n\t\t}\n\t\treturn res;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-order/src/main/java/com/alibaba/cloud/integration/order/entity/Order.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.order.entity;\n\nimport java.sql.Timestamp;\n\n/**\n * @author TrevorLink\n */\npublic class Order {\n\n\tprivate Integer id;\n\n\tprivate String userId;\n\n\tprivate String commodityCode;\n\n\tprivate Integer count;\n\n\tprivate Integer money;\n\n\tprivate Timestamp createTime;\n\n\tprivate Timestamp updateTime;\n\n\tpublic Integer getId() {\n\t\treturn id;\n\t}\n\n\tpublic void setId(Integer id) {\n\t\tthis.id = id;\n\t}\n\n\tpublic String getUserId() {\n\t\treturn userId;\n\t}\n\n\tpublic void setUserId(String userId) {\n\t\tthis.userId = userId;\n\t}\n\n\tpublic String getCommodityCode() {\n\t\treturn commodityCode;\n\t}\n\n\tpublic void setCommodityCode(String commodityCode) {\n\t\tthis.commodityCode = commodityCode;\n\t}\n\n\tpublic Integer getCount() {\n\t\treturn count;\n\t}\n\n\tpublic void setCount(Integer count) {\n\t\tthis.count = count;\n\t}\n\n\tpublic Integer getMoney() {\n\t\treturn money;\n\t}\n\n\tpublic void setMoney(Integer money) {\n\t\tthis.money = money;\n\t}\n\n\tpublic Timestamp getCreateTime() {\n\t\treturn createTime;\n\t}\n\n\tpublic void setCreateTime(Timestamp createTime) {\n\t\tthis.createTime = createTime;\n\t}\n\n\tpublic Timestamp getUpdateTime() {\n\t\treturn updateTime;\n\t}\n\n\tpublic void setUpdateTime(Timestamp updateTime) {\n\t\tthis.updateTime = updateTime;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"Order{\" + \"id=\" + id + \", userId='\" + userId + '\\'' + \", commodityCode='\"\n\t\t\t\t+ commodityCode + '\\'' + \", count=\" + count + \", money=\" + money\n\t\t\t\t+ \", createTime=\" + createTime + \", updateTime=\" + updateTime + '}';\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-order/src/main/java/com/alibaba/cloud/integration/order/feign/AccountServiceFeignClient.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.order.feign;\n\nimport com.alibaba.cloud.integration.common.Result;\nimport com.alibaba.cloud.integration.order.feign.dto.AccountDTO;\n\nimport org.springframework.cloud.openfeign.FeignClient;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\n\n/**\n * @author TrevorLink\n */\n@FeignClient(name = \"integrated-account\")\npublic interface AccountServiceFeignClient {\n\n\t@PostMapping(\"/account/reduce-balance\")\n\tResult<?> reduceBalance(@RequestBody AccountDTO accountReduceBalanceDTO);\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-order/src/main/java/com/alibaba/cloud/integration/order/feign/StorageServiceFeignClient.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.order.feign;\n\nimport com.alibaba.cloud.integration.common.Result;\nimport com.alibaba.cloud.integration.order.feign.dto.StorageDTO;\n\nimport org.springframework.cloud.openfeign.FeignClient;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\n\n/**\n * @author TrevorLink\n */\n@FeignClient(name = \"integrated-storage\")\npublic interface StorageServiceFeignClient {\n\n\t@PostMapping(\"/storage/reduce-stock\")\n\tResult<?> reduceStock(@RequestBody StorageDTO productReduceStockDTO);\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-order/src/main/java/com/alibaba/cloud/integration/order/feign/dto/AccountDTO.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.order.feign.dto;\n\n/**\n * @author TrevorLink\n */\npublic class AccountDTO {\n\n\tprivate String userId;\n\n\tprivate Integer price;\n\n\tpublic String getUserId() {\n\t\treturn userId;\n\t}\n\n\tpublic void setUserId(String userId) {\n\t\tthis.userId = userId;\n\t}\n\n\tpublic Integer getPrice() {\n\t\treturn price;\n\t}\n\n\tpublic void setPrice(Integer price) {\n\t\tthis.price = price;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-order/src/main/java/com/alibaba/cloud/integration/order/feign/dto/StorageDTO.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.order.feign.dto;\n\n/**\n * @author TrevorLink\n */\npublic class StorageDTO {\n\n\tprivate String commodityCode;\n\n\tprivate Integer count;\n\n\tpublic String getCommodityCode() {\n\t\treturn commodityCode;\n\t}\n\n\tpublic void setCommodityCode(String commodityCode) {\n\t\tthis.commodityCode = commodityCode;\n\t}\n\n\tpublic Integer getCount() {\n\t\treturn count;\n\t}\n\n\tpublic void setCount(Integer count) {\n\t\tthis.count = count;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-order/src/main/java/com/alibaba/cloud/integration/order/mapper/OrderMapper.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.order.mapper;\n\nimport com.alibaba.cloud.integration.order.entity.Order;\nimport org.apache.ibatis.annotations.Insert;\nimport org.apache.ibatis.annotations.Mapper;\nimport org.apache.ibatis.annotations.Options;\n\nimport org.springframework.stereotype.Repository;\n\n/**\n * @author TrevorLink\n */\n@Mapper\n@Repository\npublic interface OrderMapper {\n\n\t@Insert(\"INSERT INTO `order` (user_id, commodity_code,money,create_time,update_time) VALUES (#{userId}, #{commodityCode},#{money},#{createTime},#{updateTime})\")\n\t@Options(useGeneratedKeys = true, keyColumn = \"id\", keyProperty = \"id\")\n\tint saveOrder(Order order);\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-order/src/main/java/com/alibaba/cloud/integration/order/service/OrderService.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.order.service;\n\nimport com.alibaba.cloud.integration.common.BusinessException;\nimport com.alibaba.cloud.integration.common.Result;\n\n/**\n * @author TrevorLink\n */\npublic interface OrderService {\n\n\tResult<?> createOrder(String userId, String commodityCode, Integer count)\n\t\t\tthrows BusinessException;\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-order/src/main/java/com/alibaba/cloud/integration/order/service/impl/OrderServiceImpl.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.order.service.impl;\n\nimport java.sql.Timestamp;\n\nimport com.alibaba.cloud.integration.common.BusinessException;\nimport com.alibaba.cloud.integration.common.Result;\nimport com.alibaba.cloud.integration.order.entity.Order;\nimport com.alibaba.cloud.integration.order.feign.AccountServiceFeignClient;\nimport com.alibaba.cloud.integration.order.feign.StorageServiceFeignClient;\nimport com.alibaba.cloud.integration.order.feign.dto.AccountDTO;\nimport com.alibaba.cloud.integration.order.feign.dto.StorageDTO;\nimport com.alibaba.cloud.integration.order.mapper.OrderMapper;\nimport com.alibaba.cloud.integration.order.service.OrderService;\nimport org.apache.seata.core.context.RootContext;\nimport org.apache.seata.spring.annotation.GlobalTransactional;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport static com.alibaba.cloud.integration.common.ResultEnum.COMMON_FAILED;\n\n/**\n * @author TrevorLink\n */\n@Service\npublic class OrderServiceImpl implements OrderService {\n\n\tprivate Logger logger = LoggerFactory.getLogger(getClass());\n\n\t@Autowired\n\tprivate OrderMapper orderMapper;\n\n\t@Autowired\n\tprivate AccountServiceFeignClient accountService;\n\n\t@Autowired\n\tprivate StorageServiceFeignClient storageService;\n\n\t@Override\n\t@GlobalTransactional\n\tpublic Result<?> createOrder(String userId, String commodityCode, Integer count) {\n\n\t\tlogger.info(\"[createOrder] current XID: {}\", RootContext.getXID());\n\n\t\t// deduct storage\n\t\tStorageDTO storageDTO = new StorageDTO();\n\t\tstorageDTO.setCommodityCode(commodityCode);\n\t\tstorageDTO.setCount(count);\n\t\tInteger storageCode = storageService.reduceStock(storageDTO).getCode();\n\t\tif (storageCode.equals(COMMON_FAILED.getCode())) {\n\t\t\tthrow new BusinessException(\"stock not enough\");\n\t\t}\n\n\t\t// deduct balance\n\t\tint price = count * 2;\n\t\tAccountDTO accountDTO = new AccountDTO();\n\t\taccountDTO.setUserId(userId);\n\t\taccountDTO.setPrice(price);\n\t\tInteger accountCode = accountService.reduceBalance(accountDTO).getCode();\n\t\tif (accountCode.equals(COMMON_FAILED.getCode())) {\n\t\t\tthrow new BusinessException(\"balance not enough\");\n\t\t}\n\n\t\t// save order\n\t\tOrder order = new Order();\n\t\torder.setUserId(userId);\n\t\torder.setCommodityCode(commodityCode);\n\t\torder.setCount(count);\n\t\torder.setMoney(price);\n\t\torder.setCreateTime(new Timestamp(System.currentTimeMillis()));\n\t\torder.setUpdateTime(new Timestamp(System.currentTimeMillis()));\n\t\torderMapper.saveOrder(order);\n\t\tlogger.info(\"[createOrder] orderId: {}\", order.getId());\n\n\t\treturn Result.success(order);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-order/src/main/resources/application.yaml",
    "content": "server:\n  port: 8013\n\nspring:\n  application:\n    name: integrated-order\n  cloud:\n    nacos:\n      discovery:\n        server-addr: nacos-server:8848\n        group: integrated-example\n      config:\n        server-addr: nacos-server:8848\n        group: integrated-example\n        file-extension: yaml\n  config:\n    import:\n      - optional:nacos:integrated-order.yaml\n      - optional:nacos:datasource-config.yaml\n\nseata:\n  application-id: ${spring.application.name}\n  tx-service-group: ${spring.application.name}-group\n  service:\n    vgroup-mapping:\n      integrated-order-group: default\n    grouplist:\n      default: seata-server:8091\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-praise-consumer/Dockerfile",
    "content": "FROM openjdk:8-jdk-alpine as builder\n\nLABEL author=\"yuluo\" \\\n\temail=\"yuluo829@aliyun.com\"\n\nADD ./integrated-praise-consumer/target/integrated-praise-consumer-*.jar /app.jar\n\nRUN sh -c 'touch /app.jar'\nEXPOSE 8014\n\nENTRYPOINT [\"java\", \"-jar\",\"/app.jar\"]"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-praise-consumer/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n\t\t xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\t\t xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<parent>\n\t\t<artifactId>spring-cloud-alibaba-examples</artifactId>\n\t\t<groupId>com.alibaba.cloud</groupId>\n\t\t<version>${revision}</version>\n\t\t<relativePath>../../pom.xml</relativePath>\n\t</parent>\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<artifactId>integrated-praise-consumer</artifactId>\n\t<name>Spring Cloud Alibaba Integrated Praise Consumer Example</name>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-jdbc</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.mysql</groupId>\n\t\t\t<artifactId>mysql-connector-j</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba</groupId>\n\t\t\t<artifactId>druid-spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.mybatis.spring.boot</groupId>\n\t\t\t<artifactId>mybatis-spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n\t\t</dependency>\n\t</dependencies>\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-praise-consumer/src/main/java/com/alibaba/cloud/integration/consumer/PraiseConsumerApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.consumer;\n\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * @author TrevorLink\n */\n@SpringBootApplication\npublic class PraiseConsumerApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(PraiseConsumerApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-praise-consumer/src/main/java/com/alibaba/cloud/integration/consumer/controller/PraiseController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.consumer.controller;\n\nimport com.alibaba.cloud.integration.consumer.service.PraiseService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author TrevorLink\n */\n@RestController\n@RequestMapping(\"/praise\")\npublic class PraiseController {\n\n\t@Autowired\n\tprivate PraiseService praiseService;\n\n\t@GetMapping(\"/query\")\n\tpublic Integer getPraise(Integer itemId) {\n\t\treturn praiseService.getPraise(itemId);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-praise-consumer/src/main/java/com/alibaba/cloud/integration/consumer/listener/ListenerAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.consumer.listener;\n\nimport java.util.function.Consumer;\n\nimport com.alibaba.cloud.integration.consumer.message.PraiseMessage;\nimport com.alibaba.cloud.integration.consumer.service.PraiseService;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.messaging.Message;\n\n@Configuration\npublic class ListenerAutoConfiguration {\n\t@Bean\n\tpublic Consumer<Message<PraiseMessage>> consumer(PraiseService praiseService) {\n\t\treturn msg -> {\n\t\t\tpraiseService.praiseItem(msg.getPayload().getItemId());\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-praise-consumer/src/main/java/com/alibaba/cloud/integration/consumer/mapper/PraiseMapper.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.consumer.mapper;\n\nimport java.sql.Timestamp;\n\nimport org.apache.ibatis.annotations.Mapper;\nimport org.apache.ibatis.annotations.Param;\nimport org.apache.ibatis.annotations.Select;\nimport org.apache.ibatis.annotations.Update;\n\nimport org.springframework.stereotype.Repository;\n\n/**\n * @author TrevorLink\n */\n@Mapper\n@Repository\npublic interface PraiseMapper {\n\n\t@Update(\"update item set praise = praise+1,update_time=#{updateTime} where id = #{itemId}\")\n\tint praiseItem(@Param(\"itemId\") Integer itemId,\n\t\t\t@Param(\"updateTime\") Timestamp updateTime);\n\n\t@Select(\"select praise from item where id = #{itemId}\")\n\tint getPraise(@Param(\"itemId\") Integer itemId);\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-praise-consumer/src/main/java/com/alibaba/cloud/integration/consumer/message/PraiseMessage.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.consumer.message;\n\n/**\n * @author TrevorLink\n */\npublic class PraiseMessage {\n\n\tprivate Integer itemId;\n\n\tpublic Integer getItemId() {\n\t\treturn itemId;\n\t}\n\n\tpublic void setItemId(Integer itemId) {\n\t\tthis.itemId = itemId;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"PraiseMessage{\" + \"itemId=\" + itemId + '}';\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-praise-consumer/src/main/java/com/alibaba/cloud/integration/consumer/service/PraiseService.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.consumer.service;\n\n/**\n * @author TrevorLink\n */\npublic interface PraiseService {\n\n\tvoid praiseItem(Integer itemId);\n\n\tint getPraise(Integer itemId);\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-praise-consumer/src/main/java/com/alibaba/cloud/integration/consumer/service/impl/PraiseServiceImpl.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.consumer.service.impl;\n\nimport java.sql.Timestamp;\n\nimport com.alibaba.cloud.integration.consumer.mapper.PraiseMapper;\nimport com.alibaba.cloud.integration.consumer.service.PraiseService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author TrevorLink\n */\n@Service\npublic class PraiseServiceImpl implements PraiseService {\n\n\t@Autowired\n\tprivate PraiseMapper praiseMapper;\n\n\t@Override\n\tpublic void praiseItem(Integer itemId) {\n\t\tTimestamp updateTime = new Timestamp(System.currentTimeMillis());\n\t\tpraiseMapper.praiseItem(itemId, updateTime);\n\t}\n\n\t@Override\n\tpublic int getPraise(Integer itemId) {\n\t\treturn praiseMapper.getPraise(itemId);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-praise-consumer/src/main/resources/application.yaml",
    "content": "spring:\n  application:\n    name: integrated-consumer\n  cloud:\n    nacos:\n      config:\n        file-extension: yaml\n        server-addr: nacos-server:8848\n        group: integrated-example\n      discovery:\n        server-addr: nacos-server:8848\n        group: integrated-example\n  config:\n    import:\n      - optional:nacos:integrated-consumer.yaml\n      - optional:nacos:datasource-config.yaml\n\n\nserver:\n  port: 8014\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-praise-provider/Dockerfile",
    "content": "FROM openjdk:8-jdk-alpine as builder\n\nLABEL author=\"yuluo\" \\\n\temail=\"yuluo829@aliyun.com\"\n\nADD ./integrated-praise-provider/target/integrated-praise-provider-*.jar /app.jar\n\nRUN sh -c 'touch /app.jar'\nEXPOSE 8015\n\nENTRYPOINT [\"java\", \"-jar\",\"/app.jar\"]"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-praise-provider/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <groupId>com.alibaba.cloud</groupId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>integrated-praise-provider</artifactId>\n    <name>Spring Cloud Alibaba Integrated Praise Provider Example</name>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n</project>"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-praise-provider/src/main/java/com/alibaba/cloud/integration/provider/PraiseProviderApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.provider;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * @author TrevorLink\n */\n@SpringBootApplication\npublic class PraiseProviderApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(PraiseProviderApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-praise-provider/src/main/java/com/alibaba/cloud/integration/provider/controller/PraiseController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.provider.controller;\n\nimport com.alibaba.cloud.integration.provider.message.PraiseMessage;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.cloud.stream.function.StreamBridge;\nimport org.springframework.messaging.Message;\nimport org.springframework.messaging.support.MessageBuilder;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author TrevorLink\n */\n@RestController\n@RequestMapping(\"/praise\")\npublic class PraiseController {\n\tprivate static final String BINDING_NAME = \"praise-output\";\n\t@Autowired\n\tprivate StreamBridge streamBridge;\n\n\t@GetMapping({ \"/rocketmq\", \"/sentinel\" })\n\tpublic boolean praise(@RequestParam Integer itemId) {\n\t\tPraiseMessage message = new PraiseMessage();\n\t\tmessage.setItemId(itemId);\n\t\tMessage<PraiseMessage> praiseMessage = MessageBuilder.withPayload(message)\n\t\t\t\t.build();\n\t\treturn streamBridge.send(BINDING_NAME, praiseMessage);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-praise-provider/src/main/java/com/alibaba/cloud/integration/provider/message/PraiseMessage.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.provider.message;\n\n/**\n * @author TrevorLink\n */\npublic class PraiseMessage {\n\n\tprivate Integer itemId;\n\n\tpublic Integer getItemId() {\n\t\treturn itemId;\n\t}\n\n\tpublic void setItemId(Integer itemId) {\n\t\tthis.itemId = itemId;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"PraiseMessage{\" + \"itemId=\" + itemId + '}';\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-praise-provider/src/main/resources/application.yaml",
    "content": "spring:\n  application:\n    name: integrated-provider\n  cloud:\n    nacos:\n      config:\n        file-extension: yaml\n        server-addr: nacos-server:8848\n        group: integrated-example\n      discovery:\n        server-addr: nacos-server:8848\n        group: integrated-example\n  config:\n    import: optional:nacos:integrated-provider.yaml\n\nserver:\n  port: 8015\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-storage/Dockerfile",
    "content": "FROM openjdk:8-jdk-alpine as builder\n\nLABEL author=\"yuluo\" \\\n\temail=\"yuluo829@aliyun.com\"\n\nADD ./integrated-storage/target/integrated-storage-*.jar /app.jar\n\nRUN sh -c 'touch /app.jar'\nEXPOSE 8011\n\nENTRYPOINT [\"java\", \"-jar\",\"/app.jar\"]"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-storage/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <groupId>com.alibaba.cloud</groupId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>integrated-storage</artifactId>\n    <name>Spring Cloud Alibaba Integrated Storage Example</name>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-jdbc</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.mysql</groupId>\n            <artifactId>mysql-connector-j</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>druid-spring-boot-starter</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.mybatis.spring.boot</groupId>\n            <artifactId>mybatis-spring-boot-starter</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>integrated-common</artifactId>\n            <version>${revision}</version>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-storage/src/main/java/com/alibaba/cloud/integration/storage/StorageServiceApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.storage;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * @author TrevorLink\n */\n@SpringBootApplication\npublic class StorageServiceApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(StorageServiceApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-storage/src/main/java/com/alibaba/cloud/integration/storage/controller/StorageController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.storage.controller;\n\nimport com.alibaba.cloud.integration.common.BusinessException;\nimport com.alibaba.cloud.integration.common.Result;\nimport com.alibaba.cloud.integration.storage.dto.StorageDTO;\nimport com.alibaba.cloud.integration.storage.service.StorageService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author TrevorLink\n */\n@RestController\n@RequestMapping(\"/storage\")\npublic class StorageController {\n\n\t@Autowired\n\tprivate StorageService storageService;\n\n\t@PostMapping(\"/reduce-stock\")\n\tpublic Result<?> reduceStock(@RequestBody StorageDTO storageDTO) {\n\t\ttry {\n\t\t\tstorageService.reduceStock(storageDTO.getCommodityCode(),\n\t\t\t\t\tstorageDTO.getCount());\n\t\t}\n\t\tcatch (BusinessException e) {\n\t\t\treturn Result.failed(e.getMessage());\n\t\t}\n\t\treturn Result.success(\"\");\n\t}\n\n\t@GetMapping(\"/\")\n\tpublic Result<?> getRemainCount(String commodityCode) {\n\t\treturn storageService.getRemainCount(commodityCode);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-storage/src/main/java/com/alibaba/cloud/integration/storage/dto/StorageDTO.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.storage.dto;\n\n/**\n * @author TrevorLink\n */\npublic class StorageDTO {\n\n\tprivate String commodityCode;\n\n\tprivate Integer count;\n\n\tpublic String getCommodityCode() {\n\t\treturn commodityCode;\n\t}\n\n\tpublic void setCommodityCode(String commodityCode) {\n\t\tthis.commodityCode = commodityCode;\n\t}\n\n\tpublic Integer getCount() {\n\t\treturn count;\n\t}\n\n\tpublic void setCount(Integer count) {\n\t\tthis.count = count;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-storage/src/main/java/com/alibaba/cloud/integration/storage/mapper/StorageMapper.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.storage.mapper;\n\nimport java.sql.Timestamp;\n\nimport org.apache.ibatis.annotations.Mapper;\nimport org.apache.ibatis.annotations.Param;\nimport org.apache.ibatis.annotations.Select;\nimport org.apache.ibatis.annotations.Update;\n\nimport org.springframework.stereotype.Repository;\n\n/**\n * @author TrevorLink\n */\n@Mapper\n@Repository\npublic interface StorageMapper {\n\n\t@Select(\"SELECT `count` FROM storage WHERE commodity_code = #{commodityCode}\")\n\tInteger getStock(@Param(\"commodityCode\") String commodityCode);\n\n\t@Update(\"UPDATE storage SET count = count - #{count},update_time=#{updateTime} WHERE commodity_code = #{commodityCode}\")\n\tint reduceStock(@Param(\"commodityCode\") String commodityCode,\n\t\t\t@Param(\"count\") Integer count, @Param(\"updateTime\") Timestamp updateTime);\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-storage/src/main/java/com/alibaba/cloud/integration/storage/service/StorageService.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.storage.service;\n\nimport com.alibaba.cloud.integration.common.BusinessException;\nimport com.alibaba.cloud.integration.common.Result;\n\n/**\n * @author TrevorLink\n */\npublic interface StorageService {\n\n\tvoid reduceStock(String commodityCode, Integer orderCount) throws BusinessException;\n\n\tResult<?> getRemainCount(String commodityCode);\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-storage/src/main/java/com/alibaba/cloud/integration/storage/service/impl/StorageServiceImpl.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.integration.storage.service.impl;\n\nimport java.sql.Timestamp;\n\nimport com.alibaba.cloud.integration.common.BusinessException;\nimport com.alibaba.cloud.integration.common.Result;\nimport com.alibaba.cloud.integration.storage.mapper.StorageMapper;\nimport com.alibaba.cloud.integration.storage.service.StorageService;\nimport org.apache.seata.core.context.RootContext;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n/**\n * @author TrevorLink\n */\n@Service\npublic class StorageServiceImpl implements StorageService {\n\n\tprivate Logger logger = LoggerFactory.getLogger(getClass());\n\n\t@Autowired\n\tprivate StorageMapper storageMapper;\n\n\t@Override\n\t@Transactional\n\tpublic void reduceStock(String commodityCode, Integer count)\n\t\t\tthrows BusinessException {\n\t\tlogger.info(\"[reduceStock] current XID: {}\", RootContext.getXID());\n\n\t\tcheckStock(commodityCode, count);\n\n\t\tTimestamp updateTime = new Timestamp(System.currentTimeMillis());\n\t\tint updateCount = storageMapper.reduceStock(commodityCode, count, updateTime);\n\t\tif (updateCount == 0) {\n\t\t\tthrow new BusinessException(\"deduct stock failed\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic Result<?> getRemainCount(String commodityCode) {\n\t\tInteger stock = storageMapper.getStock(commodityCode);\n\t\tif (stock == null) {\n\t\t\treturn Result.failed(\"commodityCode wrong,please check commodity code\");\n\t\t}\n\t\treturn Result.success(stock);\n\t}\n\n\tprivate void checkStock(String commodityCode, Integer count)\n\t\t\tthrows BusinessException {\n\t\tInteger stock = storageMapper.getStock(commodityCode);\n\t\tif (stock < count) {\n\t\t\tthrow new BusinessException(\"no enough stock\");\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/integrated-example/integrated-storage/src/main/resources/application.yaml",
    "content": "server:\n  port: 8011\n\nspring:\n  application:\n    name: integrated-storage\n  cloud:\n    nacos:\n      discovery:\n        server-addr: nacos-server:8848\n        group: integrated-example\n      config:\n        server-addr: nacos-server:8848\n        group: integrated-example\n  config:\n    import:\n      - optional:nacos:integrated-storage.yaml\n      - optional:nacos:datasource-config.yaml\n\nseata:\n  application-id: ${spring.application.name}\n  tx-service-group: ${spring.application.name}-group\n  service:\n    vgroup-mapping:\n      integrated-storage-group: default\n    grouplist:\n      default: seata-server:8091\n\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-config-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>nacos-config-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Nacos Config Example</name>\n    <description>Example demonstrating how to use nacos config</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/java/com/alibaba/cloud/examples/NacosConfigApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * @author xiaojing, Jianwei Mao\n */\n@SpringBootApplication\npublic class NacosConfigApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(NacosConfigApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/java/com/alibaba/cloud/examples/example/BeanAutoRefreshConfigExample.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.example;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport com.alibaba.cloud.examples.model.NacosConfigInfo;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * Dynamic bean refresh example.\n *\n * @author lixiaoshuang\n */\n@RestController\n@RequestMapping(\"/nacos/bean\")\npublic class BeanAutoRefreshConfigExample {\n\n\t@Autowired\n\tprivate NacosConfigInfo nacosConfigInfo;\n\n\t@GetMapping\n\tpublic Map<String, String> getConfigInfo() {\n\t\tMap<String, String> result = new HashMap<>();\n\t\tresult.put(\"serverAddr\", nacosConfigInfo.getServerAddr());\n\t\tresult.put(\"prefix\", nacosConfigInfo.getPrefix());\n\t\tresult.put(\"group\", nacosConfigInfo.getGroup());\n\t\tresult.put(\"namespace\", nacosConfigInfo.getNamespace());\n\t\treturn result;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/java/com/alibaba/cloud/examples/example/ConfigListenerExample.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.example;\n\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.Executors;\n\n\nimport com.alibaba.cloud.nacos.NacosConfigManager;\nimport com.alibaba.nacos.api.config.ConfigService;\nimport com.alibaba.nacos.api.config.listener.Listener;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport jakarta.annotation.PostConstruct;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * Configuration listener example.\n *\n * @author lixiaoshuang\n */\n@Component\npublic class ConfigListenerExample {\n\n\tLogger logger = LoggerFactory.getLogger(ConfigListenerExample.class);\n\n\t/**\n\t * Nacos dataId.\n\t */\n\tpublic static final String DATA_ID = \"nacos-config-example.properties\";\n\n\t/**\n\t * Nacos group.\n\t */\n\tpublic static final String GROUP = \"DEFAULT_GROUP\";\n\n\t@Autowired\n\tprivate NacosConfigManager nacosConfigManager;\n\n\t@PostConstruct\n\tpublic void init() throws NacosException {\n\t\tConfigService configService = nacosConfigManager.getConfigService();\n\n\t\tconfigService.addListener(DATA_ID, GROUP, new Listener() {\n\t\t\t@Override\n\t\t\tpublic Executor getExecutor() {\n\t\t\t\treturn Executors.newSingleThreadExecutor();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void receiveConfigInfo(String configInfo) {\n\t\t\t\tlogger.info(\"[dataId]:[\" + DATA_ID + \"],Configuration changed to:\"\n\t\t\t\t\t\t+ configInfo);\n\t\t\t}\n\t\t});\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/java/com/alibaba/cloud/examples/example/DockingInterfaceExample.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.example;\n\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.Executors;\n\nimport com.alibaba.cloud.commons.lang.StringUtils;\nimport com.alibaba.cloud.nacos.NacosConfigManager;\nimport com.alibaba.nacos.api.config.ConfigService;\nimport com.alibaba.nacos.api.config.listener.Listener;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * Example of docking with Nacos interface.\n *\n * @author lixiaoshuang\n */\n@RestController\n@RequestMapping(\"/nacos\")\npublic class DockingInterfaceExample {\n\n\tLogger logger = LoggerFactory.getLogger(DockingInterfaceExample.class);\n\n\t/**\n\t * Nacos group.\n\t */\n\tpublic static final String DEFAULT_GROUP = \"DEFAULT_GROUP\";\n\n\t@Autowired\n\tprivate NacosConfigManager nacosConfigManager;\n\n\t/**\n\t * Get configuration information.\n\t *\n\t * @param dataId dataId\n\t * @param group group\n\t * @return config\n\t */\n\t@RequestMapping(\"/getConfig\")\n\tpublic String getConfig(@RequestParam(\"dataId\") String dataId,\n\t\t\t@RequestParam(value = \"group\", required = false) String group)\n\t\t\tthrows NacosException {\n\t\tif (StringUtils.isEmpty(group)) {\n\t\t\tgroup = DEFAULT_GROUP;\n\t\t}\n\t\tConfigService configService = nacosConfigManager.getConfigService();\n\t\treturn configService.getConfig(dataId, group, 2000);\n\t}\n\n\t/**\n\t * Publish configuration.\n\t *\n\t * @param dataId dataId\n\t * @param group group\n\t * @param content content\n\t * @return boolean\n\t */\n\t@RequestMapping(\"/publishConfig\")\n\tpublic boolean publishConfig(@RequestParam(\"dataId\") String dataId,\n\t\t\t@RequestParam(value = \"group\", required = false) String group,\n\t\t\t@RequestParam(\"content\") String content) throws NacosException {\n\t\tif (StringUtils.isEmpty(group)) {\n\t\t\tgroup = DEFAULT_GROUP;\n\t\t}\n\t\tConfigService configService = nacosConfigManager.getConfigService();\n\t\treturn configService.publishConfig(dataId, group, content);\n\t}\n\n\t/**\n\t * Delete configuration.\n\t *\n\t * @param dataId dataId\n\t * @param group group\n\t * @return boolean\n\t */\n\t@RequestMapping(\"/removeConfig\")\n\tpublic boolean removeConfig(@RequestParam(\"dataId\") String dataId,\n\t\t\t@RequestParam(value = \"group\", required = false) String group)\n\t\t\tthrows NacosException {\n\t\tif (StringUtils.isEmpty(group)) {\n\t\t\tgroup = DEFAULT_GROUP;\n\t\t}\n\t\tConfigService configService = nacosConfigManager.getConfigService();\n\t\treturn configService.removeConfig(dataId, group);\n\t}\n\n\t/**\n\t * Add listener configuration information.\n\t *\n\t * @param dataId dataId\n\t * @param group group\n\t */\n\t@RequestMapping(\"/listener\")\n\tpublic String listenerConfig(@RequestParam(\"dataId\") String dataId,\n\t\t\t@RequestParam(value = \"group\", required = false) String group)\n\t\t\tthrows NacosException {\n\t\tif (StringUtils.isEmpty(group)) {\n\t\t\tgroup = DEFAULT_GROUP;\n\t\t}\n\t\tConfigService configService = nacosConfigManager.getConfigService();\n\t\tconfigService.addListener(dataId, group, new Listener() {\n\t\t\t@Override\n\t\t\tpublic Executor getExecutor() {\n\t\t\t\treturn Executors.newSingleThreadExecutor();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void receiveConfigInfo(String configInfo) {\n\t\t\t\tlogger.info(\"[Listen for configuration changes]:{}\", configInfo);\n\t\t\t}\n\t\t});\n\t\treturn \"Add Lister successfully!\";\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/java/com/alibaba/cloud/examples/example/ValueAnnotationExample.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.example;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.cloud.context.config.annotation.RefreshScope;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * Use the @Value annotation to get configuration example.\n *\n * @author lixiaoshuang\n */\n@RestController\n@RequestMapping(\"/nacos/annotation\")\n@RefreshScope\npublic class ValueAnnotationExample {\n\n\t@Value(\"${spring.cloud.nacos.config.serverAddr:}\")\n\tprivate String serverAddr;\n\n\t@Value(\"${spring.cloud.nacos.config.prefix:}\")\n\tprivate String prefix;\n\n\t@Value(\"${spring.cloud.nacos.config.group:}\")\n\tprivate String group;\n\n\t@Value(\"${spring.cloud.nacos.config.namespace:}\")\n\tprivate String namespace;\n\n\t@GetMapping\n\tpublic Map<String, String> getConfigInfo() {\n\t\tMap<String, String> result = new HashMap<>(4);\n\t\tresult.put(\"serverAddr\", serverAddr);\n\t\tresult.put(\"prefix\", prefix);\n\t\tresult.put(\"group\", group);\n\t\tresult.put(\"namespace\", namespace);\n\t\treturn result;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/java/com/alibaba/cloud/examples/model/NacosConfigInfo.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.model;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author lixiaoshuang\n */\n@ConfigurationProperties(prefix = \"spring.cloud.nacos.config\")\n@Component\npublic class NacosConfigInfo {\n\n\t/**\n\t * Nacos server address.\n\t */\n\tprivate String serverAddr;\n\n\t/**\n\t * Data Id prefix.\n\t */\n\tprivate String prefix;\n\n\t/**\n\t * Nacos group.\n\t */\n\tprivate String group;\n\n\t/**\n\t * Nacos namespace.\n\t */\n\tprivate String namespace;\n\n\tpublic String getServerAddr() {\n\t\treturn serverAddr;\n\t}\n\n\tpublic void setServerAddr(String serverAddr) {\n\t\tthis.serverAddr = serverAddr;\n\t}\n\n\tpublic String getPrefix() {\n\t\treturn prefix;\n\t}\n\n\tpublic void setPrefix(String prefix) {\n\t\tthis.prefix = prefix;\n\t}\n\n\tpublic String getGroup() {\n\t\treturn group;\n\t}\n\n\tpublic void setGroup(String group) {\n\t\tthis.group = group;\n\t}\n\n\tpublic String getNamespace() {\n\t\treturn namespace;\n\t}\n\n\tpublic void setNamespace(String namespace) {\n\t\tthis.namespace = namespace;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/application.yaml",
    "content": "server:\n  port: 18084\n\nspring:\n  application:\n    name: nacos-config-example\n  cloud:\n    nacos:\n      config:\n        serverAddr: 127.0.0.1:8848\n        username: 'nacos'\n        password: 'nacos'\n  config:\n    import:\n      - nacos:nacos-config-example.properties?refreshEnabled=true\nmanagement:\n  endpoint:\n    health:\n      show-details: always\n  endpoints:\n    web:\n      exposure:\n        include: '*'\nlogging:\n  level:\n    com.alibaba.cloud.nacos.configdata: debug\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>nacos-discovery-example</artifactId>\n        <version>${revision}</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>nacos-discovery-consumer-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Nacos Discovery Consumer Example</name>\n    <description>Example demonstrating how to use nacos discovery</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-openfeign</artifactId>\n        </dependency>\n\n       <!--todo sentinel need to support GraalVM in future-->\n       <!--<dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>\n        </dependency>-->\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-loadbalancer</artifactId>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/scripts/error.sh",
    "content": "#!/usr/bin/env bash\nn=1\nwhile [ $n -le 10 ]\ndo\n    echo `curl -s http://localhost:18083/test`\n    let n++\ndone\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/scripts/feign-defaultmethod-error.sh",
    "content": "#!/usr/bin/env bash\nn=1\nwhile [ $n -le 10 ]\ndo\n    echo `curl -s http://localhost:18083/divide-feign2?a=1`\n    let n++\ndone\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/scripts/feign-error.sh",
    "content": "#!/usr/bin/env bash\nn=1\nwhile [ $n -le 10 ]\ndo\n    echo `curl -s http://localhost:18083/divide-feign?a=1\\&b=0`\n    let n++\ndone\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/scripts/index.sh",
    "content": "#!/usr/bin/env bash\nn=1\nwhile [ $n -le 10 ]\ndo\n    echo `curl -s http://localhost:18083/index`\n    let n++\ndone\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/scripts/sleep.sh",
    "content": "#!/usr/bin/env bash\nn=1\nwhile [ $n -le 10 ]\ndo\n    echo `curl -s http://localhost:18083/sleep`\n    let n++\ndone\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/src/main/java/com/alibaba/cloud/examples/ConsumerApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;\nimport org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;\nimport org.springframework.cloud.openfeign.EnableFeignClients;\n\n/**\n * @author xiaojing, fangjian0423, MieAh\n */\n@SpringBootApplication\n@EnableDiscoveryClient\n@EnableFeignClients\n@LoadBalancerClients({\n\t\t@LoadBalancerClient(\"service-provider\")\n})\npublic class ConsumerApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(ConsumerApplication.class, args);\n\t}\n\n}\n\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/src/main/java/com/alibaba/cloud/examples/TestController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\n\nimport com.alibaba.cloud.examples.feign.EchoClient;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.cloud.client.discovery.DiscoveryClient;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.client.RestTemplate;\n\n\n/**\n * Example of remote invocation of service fusing and load balancing.\n *\n * @author xiaojing, fangjian0423, MieAh\n */\n@RestController\npublic class TestController {\n\n\t@Autowired\n\tprivate RestTemplate urlCleanedRestTemplate;\n\n\t@Autowired\n\tprivate RestTemplate restTemplate;\n\n\t@Autowired\n\tprivate EchoClient echoClient;\n\n\t@Autowired\n\tprivate DiscoveryClient discoveryClient;\n\n\tprivate static final String SERVICE_PROVIDER_ADDRESS = \"http://service-provider\";\n\n\t@GetMapping(\"/echo-rest/{str}\")\n\tpublic String rest(@PathVariable String str) {\n\t\treturn urlCleanedRestTemplate\n\t\t\t\t.getForObject(SERVICE_PROVIDER_ADDRESS + \"/echo/\" + str,\n\t\t\t\t\t\tString.class);\n\t}\n\n\t@GetMapping(\"/index\")\n\tpublic String index() {\n\t\treturn restTemplate.getForObject(SERVICE_PROVIDER_ADDRESS, String.class);\n\t}\n\n\t@GetMapping(\"/test\")\n\tpublic String test() {\n\t\treturn restTemplate\n\t\t\t\t.getForObject(SERVICE_PROVIDER_ADDRESS + \"/test\", String.class);\n\t}\n\n\t@GetMapping(\"/sleep\")\n\tpublic String sleep() {\n\t\treturn restTemplate\n\t\t\t\t.getForObject(SERVICE_PROVIDER_ADDRESS + \"/sleep\", String.class);\n\t}\n\n\t@GetMapping(\"/notFound-feign\")\n\tpublic String notFound() {\n\t\treturn echoClient.notFound();\n\t}\n\n\t@GetMapping(\"/divide-feign\")\n\tpublic String divide(@RequestParam Integer a, @RequestParam Integer b) {\n\t\treturn echoClient.divide(a, b);\n\t}\n\n\t@GetMapping(\"/divide-feign2\")\n\tpublic String divide(@RequestParam Integer a) {\n\t\treturn echoClient.divide(a);\n\t}\n\n\t@GetMapping(\"/echo-feign/{str}\")\n\tpublic String feign(@PathVariable String str) {\n\t\treturn echoClient.echo(str);\n\t}\n\n\t@GetMapping(\"/services/{service}\")\n\tpublic Object client(@PathVariable String service) {\n\t\treturn discoveryClient.getInstances(service);\n\t}\n\n\t@GetMapping(\"/services\")\n\tpublic Object services() {\n\t\treturn discoveryClient.getServices();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/src/main/java/com/alibaba/cloud/examples/configuration/FeignConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.configuration;\n\nimport com.alibaba.cloud.examples.feign.EchoClient;\nimport com.alibaba.cloud.examples.feign.EchoClientFallback;\n\nimport org.springframework.context.annotation.Bean;\n\n/**\n * Configuration for Feign.\n *\n * @author fangjian0423, MieAh\n */\npublic class FeignConfiguration {\n\n\t@Bean\n\tpublic EchoClient echoClientFallback() {\n\t\treturn new EchoClientFallback();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/src/main/java/com/alibaba/cloud/examples/configuration/RestTemplateConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.configuration;\n\n\nimport org.springframework.cloud.client.loadbalancer.LoadBalanced;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * Load balancing and sentinel configuration for RestTemplate.\n *\n * @author fangjian0423, MieAh\n */\n@Configuration\npublic class RestTemplateConfiguration {\n\n\t@LoadBalanced\n\t@Bean\n\t// todo sentinel need to support GraalVM in future\n//\t@SentinelRestTemplate(urlCleanerClass = UrlCleaner.class, urlCleaner = \"clean\")\n\tpublic RestTemplate urlCleanedRestTemplate() {\n\t\treturn new RestTemplate();\n\t}\n\n\t@LoadBalanced\n\t@Bean\n\t// todo sentinel need to support GraalVM in future\n//\t@SentinelRestTemplate\n\tpublic RestTemplate restTemplate() {\n\t\treturn new RestTemplate();\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/src/main/java/com/alibaba/cloud/examples/configuration/UrlCleaner.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.configuration;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Change the request path containing echo.\n *\n * @author fangjian0423, MieAh\n */\npublic class UrlCleaner {\n\n\tprivate static final Logger LOGGER = LoggerFactory.getLogger(UrlCleaner.class);\n\n\tprivate static final String URL_CLEAN_ECHO = \".*/echo/.*\";\n\n\tpublic static String clean(String url) {\n\t\tLOGGER.info(\"enter urlCleaner\");\n\t\tif (url.matches(URL_CLEAN_ECHO)) {\n\t\t\tLOGGER.info(\"change url\");\n\t\t\turl = url.replaceAll(\"/echo/.*\", \"/echo/{str}\");\n\t\t}\n\t\treturn url;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/src/main/java/com/alibaba/cloud/examples/feign/EchoClient.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.feign;\n\n\nimport org.springframework.cloud.openfeign.FeignClient;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestParam;\n\n/**\n * Provide the external exposure interface of the service calling client.\n *\n * @author fangjian0423, MieAh\n */\n@FeignClient(name = \"service-provider\", contextId = \"service-provider\")\npublic interface EchoClient {\n\n\t/**\n\t * Call the echo method of the remote provider or roll back when the service is blown.\n\t *\n\t * @param str str\n\t * @return {@link String}\n\t */\n\t@GetMapping(\"/echo/{str}\")\n\tString echo(@PathVariable(\"str\") String str);\n\n\t/**\n\t * Call the divide method of the remote provider or roll back when the service is blown.\n\t *\n\t * @param a a\n\t * @param b b\n\t * @return {@link String}\n\t */\n\t@GetMapping(\"/divide\")\n\tString divide(@RequestParam(\"a\") Integer a, @RequestParam(\"b\") Integer b);\n\n\t/**\n\t * Test that the default method calls the remote method is still a remote call.\n\t *\n\t * @param a a\n\t * @return {@link String}\n\t */\n\tdefault String divide(Integer a) {\n\t\treturn divide(a, 0);\n\t}\n\n\t/**\n\t * Call the notFound method of the remote provider or roll back when the service is blown.\n\t *\n\t * @return {@link String}\n\t */\n\t@GetMapping(\"/notFound\")\n\tString notFound();\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/src/main/java/com/alibaba/cloud/examples/feign/EchoClientFallback.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.feign;\n\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestParam;\n\n/**\n * When the service is blown, the fallback operation is performed.\n *\n * @author fangjian0423, MieAh\n */\npublic class EchoClientFallback implements EchoClient {\n\n\t@Override\n\tpublic String echo(@PathVariable(\"str\") String str) {\n\t\treturn \"echo fallback\";\n\t}\n\n\t@Override\n\tpublic String divide(@RequestParam Integer a, @RequestParam Integer b) {\n\t\treturn \"divide fallback\";\n\t}\n\n\t@Override\n\tpublic String notFound() {\n\t\treturn \"notFound fallback\";\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/src/main/resources/application.properties",
    "content": "spring.application.name=service-consumer\nserver.port=18083\nmanagement.endpoints.web.exposure.include=*\nspring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\nspring.cloud.nacos.discovery.fail-fast=true\n\nspring.cloud.nacos.username=nacos\nspring.cloud.nacos.password=nacos\n\nfeign.sentinel.enabled=true\n\nspring.cloud.sentinel.transport.dashboard=localhost:8080\nspring.cloud.sentinel.eager=true\n\nspring.cloud.sentinel.datasource.ds1.file.file=classpath: flowrule.json\nspring.cloud.sentinel.datasource.ds1.file.data-type=json\nspring.cloud.sentinel.datasource.ds1.file.rule-type=flow\n\nspring.cloud.sentinel.datasource.ds2.file.file=classpath: degraderule.json\nspring.cloud.sentinel.datasource.ds2.file.data-type=json\nspring.cloud.sentinel.datasource.ds2.file.rule-type=degrade\nspring.cloud.loadbalancer.nacos.enabled=true\n# use feign client in GraalVM environment need to set below config\nspring.cloud.refresh.enabled=false\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/src/main/resources/degraderule.json",
    "content": "[\n  {\n    \"resource\": \"GET:http://service-provider/test\",\n    \"count\": 0.5,\n    \"grade\": 1,\n    \"timeWindow\": 30\n  },\n  {\n    \"resource\": \"GET:http://service-provider\",\n    \"count\": 0.5,\n    \"grade\": 1,\n    \"timeWindow\": 10\n  },\n  {\n    \"resource\": \"GET:http://service-provider/sleep\",\n    \"count\": 20.0,\n    \"grade\": 0,\n    \"timeWindow\": 30\n  },\n  {\n    \"resource\": \"GET:http://service-provider/divide\",\n    \"count\": 0.5,\n    \"grade\": 1,\n    \"timeWindow\": 30\n  }\n]"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/src/main/resources/flowrule.json",
    "content": "[\n  {\n    \"resource\": \"GET:http://service-provider/echo/{str}\",\n    \"controlBehavior\": 0,\n    \"count\": 1,\n    \"grade\": 1,\n    \"limitApp\": \"default\",\n    \"strategy\": 0\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>nacos-discovery-example</artifactId>\n        <version>${revision}</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>nacos-discovery-consumer-sclb-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Nacos Discovery x Load Balancer Example</name>\n    <description>Example demonstrating how to use nacos discovery</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.springframework.cloud</groupId>\n                    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-loadbalancer</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-commons</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-openfeign</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.springframework.cloud</groupId>\n                    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/scripts/error.sh",
    "content": "#!/usr/bin/env bash\nn=1\nwhile [ $n -le 10 ]\ndo\n    echo `curl -s http://localhost:18083/test`\n    let n++\ndone\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/scripts/feign-defaultmethod-error.sh",
    "content": "#!/usr/bin/env bash\nn=1\nwhile [ $n -le 10 ]\ndo\n    echo `curl -s http://localhost:18083/divide-feign2?a=1`\n    let n++\ndone\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/scripts/feign-error.sh",
    "content": "#!/usr/bin/env bash\nn=1\nwhile [ $n -le 10 ]\ndo\n    echo `curl -s http://localhost:18083/divide-feign?a=1\\&b=0`\n    let n++\ndone\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/scripts/index.sh",
    "content": "#!/usr/bin/env bash\nn=1\nwhile [ $n -le 10 ]\ndo\n    echo `curl -s http://localhost:18083/index`\n    let n++\ndone\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/scripts/resttemplate.sh",
    "content": "#!/usr/bin/env bash\nn=1\nwhile [ $n -le 10 ]\ndo\n    echo `curl -s http://localhost:18083/echo-rest/resttemplate`\n    let n++\ndone\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/scripts/sleep.sh",
    "content": "#!/usr/bin/env bash\nn=1\nwhile [ $n -le 10 ]\ndo\n    echo `curl -s http://localhost:18083/sleep`\n    let n++\ndone\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/ConsumerSCLBApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.openfeign.EnableFeignClients;\n\n\n/**\n *\n * @author fangjian0423, MieAh\n */\n@SpringBootApplication\n@EnableDiscoveryClient(autoRegister = false)\n@EnableFeignClients\npublic class ConsumerSCLBApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(ConsumerSCLBApplication.class, args);\n\t}\n\n}\n\n\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/RandomLoadBalancer.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport java.util.List;\nimport java.util.Random;\n\nimport reactor.core.publisher.Mono;\n\nimport org.springframework.beans.factory.ObjectProvider;\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.cloud.client.loadbalancer.DefaultResponse;\nimport org.springframework.cloud.client.loadbalancer.EmptyResponse;\nimport org.springframework.cloud.client.loadbalancer.Response;\nimport org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier;\nimport org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;\nimport org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;\n\n/**\n * Self-defined randomLoadBalancer.\n *\n * @author fangjian0423, MieAh\n */\npublic class RandomLoadBalancer implements ReactorServiceInstanceLoadBalancer {\n\n\tprivate ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;\n\n\tprivate final String serviceId;\n\n\tprivate final Random random;\n\n\tpublic RandomLoadBalancer(\n\t\t\tObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider,\n\t\t\tString serviceId) {\n\t\tthis.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;\n\t\tthis.serviceId = serviceId;\n\t\tthis.random = new Random();\n\t}\n\n\t@Override\n\tpublic Mono<Response<ServiceInstance>> choose(\n\t\t\torg.springframework.cloud.client.loadbalancer.Request request) {\n\t\tServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider\n\t\t\t\t.getIfAvailable(NoopServiceInstanceListSupplier::new);\n\n\t\treturn supplier.get().next().map(this::getInstanceResponse);\n\t}\n\n\t@Override\n\tpublic Mono<Response<ServiceInstance>> choose() {\n\t\tServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider\n\t\t\t\t.getIfAvailable(NoopServiceInstanceListSupplier::new);\n\t\treturn supplier.get().next().map(this::getInstanceResponse);\n\t}\n\n\tprivate Response<ServiceInstance> getInstanceResponse(\n\t\t\tList<ServiceInstance> instances) {\n\t\tif (instances.isEmpty()) {\n\t\t\treturn new EmptyResponse();\n\t\t}\n\t\tServiceInstance instance = instances.get(random.nextInt(instances.size()));\n\n\t\treturn new DefaultResponse(instance);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/TestController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport com.alibaba.cloud.examples.feign.EchoClient;\nimport jakarta.annotation.Resource;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.cloud.client.discovery.DiscoveryClient;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.client.RestTemplate;\n\n\n/**\n * Example of remote invocation of service fusing and custom load balancing.\n *\n * @author fangjian0423, MieAh\n */\n@RestController\npublic class TestController {\n\n\t@Resource\n\tprivate RestTemplate urlCleanedRestTemplate;\n\n\t@Resource\n\tprivate RestTemplate restTemplate;\n\n\t@Resource\n\tprivate EchoClient echoClient;\n\n\t@Resource\n\tprivate DiscoveryClient discoveryClient;\n\n\t@Value(\"${spring.cloud.loadbalancer.zone:null}\")\n\tprivate String zone;\n\n\tprivate static final String SERVICE_PROVIDER_ADDRESS = \"http://service-provider\";\n\n\t@GetMapping(\"/echo-rest/{str}\")\n\tpublic String rest(@PathVariable String str) {\n\t\treturn urlCleanedRestTemplate\n\t\t\t\t.getForObject(SERVICE_PROVIDER_ADDRESS + \"/echo/\" + str,\n\t\t\t\t\t\tString.class);\n\t}\n\n\t@GetMapping(\"/zone\")\n\tpublic String zone() {\n\t\treturn \"consumer zone \" + zone + \"\\n\" + urlCleanedRestTemplate\n\t\t\t\t.getForObject(SERVICE_PROVIDER_ADDRESS + \"/zone\", String.class);\n\t}\n\n\t@GetMapping(\"/echo-feign/{str}\")\n\tpublic String feign(@PathVariable String str) {\n\t\treturn echoClient.echo(str);\n\t}\n\n\t@GetMapping(\"/index\")\n\tpublic String index() {\n\t\treturn restTemplate.getForObject(SERVICE_PROVIDER_ADDRESS, String.class);\n\t}\n\n\t@GetMapping(\"/test\")\n\tpublic String test() {\n\t\treturn restTemplate.getForObject(SERVICE_PROVIDER_ADDRESS + \"/test\",\n\t\t\t\tString.class);\n\t}\n\n\t@GetMapping(\"/sleep\")\n\tpublic String sleep() {\n\t\treturn restTemplate.getForObject(SERVICE_PROVIDER_ADDRESS + \"/sleep\",\n\t\t\t\tString.class);\n\t}\n\n\t@GetMapping(\"/notFound-feign\")\n\tpublic String notFound() {\n\t\treturn echoClient.notFound();\n\t}\n\n\t@GetMapping(\"/divide-feign\")\n\tpublic String divide(@RequestParam Integer a, @RequestParam Integer b) {\n\t\treturn echoClient.divide(a, b);\n\t}\n\n\t@GetMapping(\"/divide-feign2\")\n\tpublic String divide(@RequestParam Integer a) {\n\t\treturn echoClient.divide(a);\n\t}\n\n\t@GetMapping(\"/services/{service}\")\n\tpublic Object client(@PathVariable String service) {\n\t\treturn discoveryClient.getInstances(service);\n\t}\n\n\t@GetMapping(\"/services\")\n\tpublic Object services() {\n\t\treturn discoveryClient.getServices();\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/config/FeignConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.config;\n\nimport com.alibaba.cloud.examples.feign.EchoClient;\nimport com.alibaba.cloud.examples.feign.EchoClientFallback;\n\nimport org.springframework.context.annotation.Bean;\n\n\n/**\n * Configuration for Feign.\n *\n * @author fangjian0423, MieAh\n */\npublic class FeignConfiguration {\n\n\t@Bean\n\tpublic EchoClient echoClientFallback() {\n\t\treturn new EchoClientFallback();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/config/MyLoadBalancerConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.config;\n\nimport com.alibaba.cloud.examples.RandomLoadBalancer;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;\nimport org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;\nimport org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.core.env.Environment;\n\n\n/**\n * Configure for load balancing.\n *\n * @author fangjian0423, MieAh\n */\npublic class MyLoadBalancerConfiguration {\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\tpublic ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(\n\t\t\tEnvironment environment,\n\t\t\tLoadBalancerClientFactory loadBalancerClientFactory) {\n\t\tString name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);\n\t\treturn new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name,\n\t\t\t\tServiceInstanceListSupplier.class), name);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/config/MySCLBConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.config;\n\nimport org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * Configuration for Self-defined randomLoadBalancer.\n *\n * @author fangjian0423, MieAh\n */\n@Configuration\n@LoadBalancerClient(value = \"service-provider\", configuration = MyLoadBalancerConfiguration.class)\npublic class MySCLBConfiguration {\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/config/RestTemplateConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.config;\n\nimport com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;\n\nimport org.springframework.cloud.client.loadbalancer.LoadBalanced;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * Load balancing and sentinel configuration for RestTemplate.\n *\n * @author fangjian0423, MieAh\n */\n@Configuration\npublic class RestTemplateConfiguration {\n\n\t@LoadBalanced\n\t@Bean\n\t@SentinelRestTemplate(urlCleanerClass = UrlCleaner.class, urlCleaner = \"clean\")\n\tpublic RestTemplate urlCleanedRestTemplate() {\n\t\treturn new RestTemplate();\n\t}\n\n\t@LoadBalanced\n\t@Bean\n\t@SentinelRestTemplate\n\tpublic RestTemplate restTemplate() {\n\t\treturn new RestTemplate();\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/config/UrlCleaner.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.config;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Change the request path containing echo.\n *\n * @author fangjian0423, MieAh\n */\npublic class UrlCleaner {\n\n\tprivate static final Logger LOGGER = LoggerFactory.getLogger(UrlCleaner.class);\n\n\tprivate static final String URL_CLEAN_ECHO = \".*/echo/.*\";\n\n\tpublic static String clean(String url) {\n\t\tLOGGER.info(\"enter urlCleaner\");\n\t\tif (url.matches(URL_CLEAN_ECHO)) {\n\t\t\tLOGGER.info(\"change url\");\n\t\t\turl = url.replaceAll(\"/echo/.*\", \"/echo/{str}\");\n\t\t}\n\t\treturn url;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/feign/EchoClient.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.feign;\n\nimport com.alibaba.cloud.examples.config.FeignConfiguration;\n\nimport org.springframework.cloud.openfeign.FeignClient;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestParam;\n\n/**\n * Provide the external exposure interface of the service calling client.\n *\n * @author fangjian0423, MieAh\n */\n@FeignClient(name = \"service-provider\", fallback = EchoClientFallback.class, configuration = FeignConfiguration.class)\npublic interface EchoClient {\n\n\t/**\n\t * Call the echo method of the remote provider or roll back when the service is blown.\n\t *\n\t * @param str str\n\t * @return {@link String}\n\t */\n\t@GetMapping(\"/echo/{str}\")\n\tString echo(@PathVariable(\"str\") String str);\n\n\t/**\n\t * Call the divide method of the remote provider or roll back when the service is blown.\n\t *\n\t * @param a a\n\t * @param b b\n\t * @return {@link String}\n\t */\n\t@GetMapping(\"/divide\")\n\tString divide(@RequestParam(\"a\") Integer a, @RequestParam(\"b\") Integer b);\n\n\t/**\n\t * Test that the default method calls the remote method is still a remote call.\n\t *\n\t * @param a a\n\t * @return {@link String}\n\t */\n\tdefault String divide(Integer a) {\n\t\treturn divide(a, 0);\n\t}\n\n\t/**\n\t * Call the notFound method of the remote provider or roll back when the service is blown.\n\t *\n\t * @return {@link String}\n\t */\n\t@GetMapping(\"/notFound\")\n\tString notFound();\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/feign/EchoClientFallback.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.feign;\n\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestParam;\n\n/**\n * When the service is blown, the fallback operation is performed.\n *\n * @author fangjian0423, MieAh\n */\npublic class EchoClientFallback implements EchoClient {\n\n\t@Override\n\tpublic String echo(@PathVariable(\"str\") String str) {\n\t\treturn \"echo fallback\";\n\t}\n\n\t@Override\n\tpublic String divide(@RequestParam Integer a, @RequestParam Integer b) {\n\t\treturn \"divide fallback\";\n\t}\n\n\t@Override\n\tpublic String notFound() {\n\t\treturn \"notFound fallback\";\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/resources/application.properties",
    "content": "spring.application.name=service-consumer-sclb\nserver.port=18083\nmanagement.endpoints.web.exposure.include=*\nspring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\n\nspring.cloud.nacos.username=nacos\nspring.cloud.nacos.password=nacos\n\nspring.cloud.loadbalancer.ribbon.enabled=false\nspring.cloud.loadbalancer.configurations=zone-preference\nspring.cloud.loadbalancer.zone=hangzhou\n\nfeign.sentinel.enabled=true\n\nspring.cloud.sentinel.transport.dashboard=localhost:8080\nspring.cloud.sentinel.eager=true\n\nspring.cloud.sentinel.datasource.ds1.file.file=classpath: flowrule.json\nspring.cloud.sentinel.datasource.ds1.file.data-type=json\nspring.cloud.sentinel.datasource.ds1.file.rule-type=flow\n\nspring.cloud.sentinel.datasource.ds2.file.file=classpath: degraderule.json\nspring.cloud.sentinel.datasource.ds2.file.data-type=json\nspring.cloud.sentinel.datasource.ds2.file.rule-type=degrade\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/resources/degraderule.json",
    "content": "[\n  {\n    \"resource\": \"GET:http://service-provider/test\",\n    \"count\": 0.5,\n    \"grade\": 1,\n    \"timeWindow\": 30\n  },\n  {\n    \"resource\": \"GET:http://service-provider\",\n    \"count\": 0.5,\n    \"grade\": 1,\n    \"timeWindow\": 10\n  },\n  {\n    \"resource\": \"GET:http://service-provider/sleep\",\n    \"count\": 20.0,\n    \"grade\": 0,\n    \"timeWindow\": 30\n  },\n  {\n    \"resource\": \"GET:http://service-provider/divide\",\n    \"count\": 0.5,\n    \"grade\": 1,\n    \"timeWindow\": 30\n  }\n]"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/resources/flowrule.json",
    "content": "[\n  {\n    \"resource\": \"GET:http://service-provider/echo/{str}\",\n    \"controlBehavior\": 0,\n    \"count\": 2,\n    \"grade\": 1,\n    \"limitApp\": \"default\",\n    \"strategy\": 0\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>nacos-discovery-example</artifactId>\n        <version>${revision}</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>nacos-discovery-provider-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Nacos Discovery Provider Example</name>\n    <description>Example demonstrating how to use nacos discovery</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/java/com/alibaba/cloud/examples/EchoController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport java.util.Map;\n\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport jakarta.annotation.Resource;\n\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n\n/**\n * Provide interfaces to consumers.\n *\n * @author fangjian0423, MieAh\n */\n@RestController\npublic class EchoController {\n\n\t@Resource\n\tprivate NacosDiscoveryProperties nacosDiscoveryProperties;\n\n\t@GetMapping(\"/\")\n\tpublic ResponseEntity<String> index() {\n\t\treturn new ResponseEntity<>(\"index error\", HttpStatus.INTERNAL_SERVER_ERROR);\n\t}\n\n\t@GetMapping(\"/test\")\n\tpublic ResponseEntity<String> test() {\n\t\treturn new ResponseEntity<>(\"error\", HttpStatus.INTERNAL_SERVER_ERROR);\n\t}\n\n\t@GetMapping(\"/sleep\")\n\tpublic String sleep() {\n\t\ttry {\n\t\t\tThread.sleep(1000L);\n\t\t}\n\t\tcatch (InterruptedException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\treturn \"ok\";\n\t}\n\n\t@GetMapping(\"/echo/{string}\")\n\tpublic String echo(@PathVariable String string) {\n\t\treturn \"hello Nacos Discovery \" + string;\n\t}\n\n\t@GetMapping(\"/divide\")\n\tpublic String divide(@RequestParam Integer a, @RequestParam Integer b) {\n\t\tif (b == 0) {\n\t\t\treturn String.valueOf(0);\n\t\t}\n\t\telse {\n\t\t\treturn String.valueOf(a / b);\n\t\t}\n\t}\n\n\t@GetMapping(\"/zone\")\n\tpublic String zone() {\n\t\tMap<String, String> metadata = nacosDiscoveryProperties.getMetadata();\n\t\treturn \"provider zone \" + metadata.get(\"zone\");\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/java/com/alibaba/cloud/examples/ProviderApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\n\n\n/**\n * @author xiaojing, fangjian0423, MieAh\n */\n@EnableDiscoveryClient\n@SpringBootApplication\npublic class ProviderApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(ProviderApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/resources/application.properties",
    "content": "server.port=0\nspring.application.name=service-provider\nspring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\nspring.cloud.nacos.discovery.enabled=true\n#spring.cloud.nacos.discovery.instance-enabled=true\n#only register IPv4 instance\n#spring.cloud.nacos.discovery.ip-type=IPv4\n#only register IPv6 instance\n#spring.cloud.nacos.discovery.ip-type=IPv6\n\nspring.cloud.nacos.username=nacos\nspring.cloud.nacos.password=nacos\n\nmanagement.endpoints.web.exposure.include=*\nmanagement.endpoint.health.show-details=always\n\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-spring-cloud-config-client-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>nacos-discovery-example</artifactId>\n        <version>${revision}</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>nacos-discovery-spring-cloud-config-client-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Nacos Discovery x Config Client Example</name>\n    <description>Example demonstrating how to use nacos discovery</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-config</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-spring-cloud-config-client-example/src/main/java/com/alibaba/cloud/examples/GetConfigController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * Provide the interface method of config.\n *\n * @author MieAh\n */\n@RestController\npublic class GetConfigController {\n\n\t@Value(\"${config}\")\n\tprivate String config;\n\n\t@GetMapping(\"/config\")\n\tpublic String getConfig() {\n\t\treturn config;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-spring-cloud-config-client-example/src/main/java/com/alibaba/cloud/examples/SpringCloudConfigClientApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\n\n/**\n * @author JevonYang\n */\n@SpringBootApplication\n@EnableDiscoveryClient\npublic class SpringCloudConfigClientApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(SpringCloudConfigClientApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-spring-cloud-config-client-example/src/main/resources/application.yml",
    "content": "server:\n  port: 18083\nspring:\n  application:\n    name: client\n  config:\n    import: optional:configserver:http://localhost:7070\n  cloud:\n    nacos:\n      username: nacos\n      password: nacos\n      discovery:\n        server-addr: 127.0.0.1:8848\nconfig: config-from-yml\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-spring-cloud-config-server-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>nacos-discovery-example</artifactId>\n        <version>${revision}</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>nacos-discovery-spring-cloud-config-server-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Nacos Discovery x Config Server Example</name>\n    <description>Example demonstrating how to use nacos discovery</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-config-server</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-spring-cloud-config-server-example/src/main/java/com/alibaba/cloud/examples/SpringCloudConfigServerApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.config.server.EnableConfigServer;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@SpringBootApplication\n@EnableDiscoveryClient\n@EnableConfigServer\npublic class SpringCloudConfigServerApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(SpringCloudConfigServerApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-spring-cloud-config-server-example/src/main/resources/application.yml",
    "content": "server:\n  port: 7070\n\nspring:\n  application:\n    name: configserver\n  cloud:\n    nacos:\n      username: 'nacos'\n      password: 'nacos'\n      discovery:\n        server-addr: 127.0.0.1:8848\n    config:\n      server:\n        git:\n          uri: https://github.com/fangjian0423/blogimages\n          search-paths: /\n\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>nacos-discovery-example</artifactId>\n        <version>${revision}</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>nacos-reactivediscovery-consumer-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Nacos Discovery Reactive Example</name>\n    <description>Example demonstrating how to use nacos discovery</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-webflux</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.springframework.cloud</groupId>\n                    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-loadbalancer</artifactId>\n        </dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/java/com/alibaba/cloud/examples/ConsumerReactiveApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;\nimport org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n\n@SpringBootApplication\n@LoadBalancerClients({\n\t\t@LoadBalancerClient(\"service-provider\")\n})\npublic class ConsumerReactiveApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(ConsumerReactiveApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/java/com/alibaba/cloud/examples/MyController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport jakarta.annotation.Resource;\nimport reactor.core.publisher.Flux;\nimport reactor.core.publisher.Mono;\n\nimport org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.reactive.function.client.WebClient;\n\n\n/**\n * Example of responsive discovery client.\n *\n * @author fangjian0423, MieAh\n */\n@RestController\npublic class MyController {\n\n\t@Resource\n\tprivate ReactiveDiscoveryClient reactiveDiscoveryClient;\n\n\t@Resource\n\tprivate WebClient.Builder webClientBuilder;\n\n\t@GetMapping(\"/all-services\")\n\tpublic Flux<String> allServices() {\n\t\treturn reactiveDiscoveryClient.getInstances(\"service-provider\")\n\t\t\t\t.map(serviceInstance -> serviceInstance.getHost() + \":\"\n\t\t\t\t\t\t+ serviceInstance.getPort());\n\t}\n\n\t@GetMapping(\"/service-call/{name}\")\n\tpublic Mono<String> serviceCall(@PathVariable(\"name\") String name) {\n\t\treturn webClientBuilder.build().get()\n\t\t\t\t.uri(\"http://service-provider/echo/\" + name).retrieve()\n\t\t\t\t.bodyToMono(String.class);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/java/com/alibaba/cloud/examples/WebClientConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.cloud.client.loadbalancer.LoadBalanced;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.reactive.function.client.WebClient;\n\n/**\n * Configuration for web client.\n *\n * @author fangjian0423, MieAh\n */\n\n@Configuration\npublic class WebClientConfiguration {\n\n\t@Bean\n\t@LoadBalanced\n\tpublic WebClient.Builder webClient() {\n\t\treturn WebClient.builder();\n\t}\n}\n\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/resources/application.properties",
    "content": "spring.application.name=service-consumer-reactive\nserver.port=18083\nmanagement.endpoints.web.exposure.include=*\nspring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\n\nspring.cloud.nacos.username=nacos\nspring.cloud.nacos.password=nacos\n\nspring.cloud.loadbalancer.ribbon.enabled=false\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>nacos-discovery-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Nacos Discovery Examples</name>\n    <description>Example demonstrating how to use nacos discovery</description>\n    <packaging>pom</packaging>\n\n\n    <modules>\n        <module>nacos-discovery-consumer-example</module>\n        <module>nacos-discovery-consumer-sclb-example</module>\n        <module>nacos-reactivediscovery-consumer-example</module>\n        <module>nacos-discovery-provider-example</module>\n        <module>nacos-discovery-spring-cloud-config-server-example</module>\n        <module>nacos-discovery-spring-cloud-config-client-example</module>\n    </modules>\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-gateway-example/nacos-gateway-discovery-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>nacos-gateway-example</artifactId>\n        <version>${revision}</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>nacos-gateway-discovery-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Nacos Discovery x Gateway Example</name>\n    <description>Example demonstrating how to use gateway with nacos</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-gateway-server-webflux</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-loadbalancer</artifactId>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-gateway-example/nacos-gateway-discovery-example/src/main/java/com/alibaba/cloud/examples/GatewayApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;\nimport org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;\n\n/**\n * @author lengleng\n */\n@SpringBootApplication\n@EnableDiscoveryClient\n@LoadBalancerClients({\n\t\t@LoadBalancerClient(\"service-gateway-provider\")\n})\npublic class GatewayApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(GatewayApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-gateway-example/nacos-gateway-discovery-example/src/main/resources/application.properties",
    "content": "server.port=18085\nspring.application.name=service-gateway\nspring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\n\nspring.cloud.nacos.username=nacos\nspring.cloud.nacos.password=nacos\n\nmanagement.endpoints.web.exposure.include=*\n\n# spring cloud route config\nspring.cloud.gateway.server.webflux.routes[0].id=nacos-route\nspring.cloud.gateway.server.webflux.routes[0].uri=lb://service-gateway-provider\nspring.cloud.gateway.server.webflux.routes[0].predicates[0].name=Path\nspring.cloud.gateway.server.webflux.routes[0].predicates[0].args[pattern]=/nacos/**\nspring.cloud.gateway.server.webflux.routes[0].filters[0]=StripPrefix=1\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-gateway-example/nacos-gateway-provider-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>nacos-gateway-example</artifactId>\n        <version>${revision}</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>nacos-gateway-provider-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Nacos Discovery x Gateway - Provider Example</name>\n    <description>Example demonstrating how to use gateway with nacos</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-gateway-example/nacos-gateway-provider-example/src/main/java/com/alibaba/cloud/examples/EchoController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * Provide a service interface to the gateway for forwarding calls.\n *\n * @author MieAh\n */\n@RestController\npublic class EchoController {\n\n\t@GetMapping(\"/echo/{string}\")\n\tpublic String echo(@PathVariable String string) {\n\t\treturn \"hello Nacos Discovery \" + string;\n\t}\n\n\t@GetMapping(\"/divide\")\n\tpublic String divide(@RequestParam Integer a, @RequestParam Integer b) {\n\t\treturn String.valueOf(a / b);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-gateway-example/nacos-gateway-provider-example/src/main/java/com/alibaba/cloud/examples/ProviderApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\n\n/**\n * @author xiaojing\n */\n@SpringBootApplication\n@EnableDiscoveryClient\npublic class ProviderApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(ProviderApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-gateway-example/nacos-gateway-provider-example/src/main/resources/application.properties",
    "content": "server.port=18086\nspring.application.name=service-gateway-provider\nspring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\n\nspring.cloud.nacos.username=nacos\nspring.cloud.nacos.password=nacos\n\nmanagement.endpoints.web.exposure.include=*\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/nacos-gateway-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>nacos-gateway-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Nacos Discovery x Gateway Examples</name>\n    <description>Example demonstrating how to use gateway with nacos</description>\n    <packaging>pom</packaging>\n\n\n    <modules>\n        <module>nacos-gateway-discovery-example</module>\n        <module>nacos-gateway-provider-example</module>\n    </modules>\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/readme-zh.md",
    "content": "# Spring Cloud Alibaba Nacos Example\n\n## 项目说明\n\n本项目演示如何使用 Spring Cloud Alibaba Nacos 相关 Starter 完成 Spring Cloud 应用的服务发现和配置管理。\n\n[Nacos](https://github.com/alibaba/Nacos) 是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。\n\n## 正确配置并启动 Nacos Server 3.1.0\n\n在 Nacos 3.1.0 中，加入了用户鉴权相关的功能，在首次启动 Nacos Server 时，需要正确配置，避免出现启动失败的问题。\n\n### 下载 Nacos Server\n\n> 本示例中使用 Nacos Server 版本为 3.1.0！\n\nNacos 支持直接下载和源码构建两种方式。**推荐在 Spring Cloud Alibaba 2023.x 中使用 Nacos Server 3.1.0 版本。**\n\n1. 直接下载：[Nacos Server 下载页](https://github.com/alibaba/nacos/releases)\n2. 源码构建：进入 Nacos [Github 项目页面](https://github.com/alibaba/nacos)，将代码 git clone 到本地自行编译打包，[参考文档](https://nacos.io/zh-cn/docs/quick-start.html)。\n\n### 配置 Nacos Server\n\n打开 `\\nacos-server-3.1.0\\conf\\application.properties` 配置文件，修改以下配置项：\n\n#### 配置数据源\n\n此处以 MySQL 数据库为例，使用 `nacos-server-3.1.0\\conf\\mysql-schema.sql` 初始化数据库表文件。同时修改以下配置\n\n```properties\n#*************** Config Module Related Configurations ***************#\n### If use MySQL as datasource:\nspring.datasource.platform=mysql\n\n### Count of DB:\ndb.num=1\n\n### Connect URL of DB:\ndb.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true\ndb.user.0=root\ndb.password.0=root\n\n### Connection pool configuration: hikariCP\ndb.pool.config.connectionTimeout=30000\ndb.pool.config.validationTimeout=10000\ndb.pool.config.maximumPoolSize=20\ndb.pool.config.minimumIdle=2\n```\n\n#### 开启鉴权\n\n**注意：不开启在 3.1.0 中会出现登陆失败异常！**\n\n```properties\n### The auth system to use, currently only 'nacos' and 'ldap' is supported:\nnacos.core.auth.system.type=nacos\n\n### If turn on auth system:\nnacos.core.auth.enabled=true\n```\n\n#### 设置服务端验证 key\n\n```properties\nnacos.core.auth.server.identity.key=test\nnacos.core.auth.server.identity.value=test\n```\n\n#### 设置默认 token\n\n```properties\n### The default token (Base64 String):\nnacos.core.auth.plugin.nacos.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789\n```\n\n**在使用 Nacos 服务发现和配置功能时，一定要配置 `username` 和 `password` 属性，否则会出现用户未找到异常！**\n\n#### Open API 鉴权\n\n在 nacos server 3.1.0 中使用 Open api 接口时需要鉴权：更多细节请参考：[Nacos api 鉴权](https://nacos.io/zh-cn/docs/auth.html)\n\n1. 获取 accessToken：使用用户名和密码登陆 nacos server：\n\n   `curl -X POST '127.0.0.1:8848/nacos/v1/auth/login' -d 'username=nacos&password=nacos'`\n\n   若用户名和密码正确,返回信息如下:\n\n   `{\"accessToken\":\"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYwNTYyOTE2Nn0.2TogGhhr11_vLEjqKko1HJHUJEmsPuCxkur-CfNojDo\",\"tokenTtl\":18000,\"globalAdmin\":true}`\n\n2. 使用 accessToken 请求 nacos api 接口：\n   \n   `curl -X GET '127.0.0.1:8848/nacos/v1/cs/configs?accessToken=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYwNTYyMzkyM30.O-s2yWfDSUZ7Svd3Vs7jy9tsfDNHs1SuebJB4KlNY8Q&dataId=nacos.example.1&group=nacos_group'`\n\n### 启动 Nacos Server\n\n1. 启动 Nacos Server，进入下载到本地并解压完成后的文件夹(使用源码构建的方式则进入编译打包好的文件夹)，再进去其相对文件夹 `nacos/bin`，并对照操作系统实际情况执行如下命令。[详情参考此文档](https://nacos.io/zh-cn/docs/quick-start.html)。\n\n   1. Linux/Unix/Mac 操作系统，执行命令 \n\n      `sh startup.sh -m standalone`\n\n   2. Windows 操作系统，执行命令 \n\n      `cmd startup.cmd`\n\n2. 访问 Nacos Server Console\n\n   浏览器输入地址 http://127.0.0.1:8848/nacos ，**首次登陆需要绑定 nacos 用户，因为新版本增加了鉴权，需要应用注册和配置绑定时配置用户名和密码。**\n\n## Nacos 应用示例\n\n### Spring Cloud Alibaba Nacos Config\n\n#### 配置方式更新说明\n\n在2023.0.1.3版本中，为了支持在SpringBoot中接入Nacos配置中心以及基于原有的nacos config模块之上支持@NacosConfig，@NacosConfigListener注解，将spring-cloud-starter-alibaba-nacos-config模块进行了拆分\n\n- **spring-alibaba-nacos-config**：仅依赖SpringBoot，支持在非SpringCloud应用中独立使用\n- **spring-cloud-starter-alibaba-nacos-config**：仅保留依赖SpringCloud的组件\n\n在模块拆分的过程中，发现随着代码不断的变更，配置的加载逻辑存在多个分支，包括最初版本中通过拼接spring.application.name以及fileExtension等参数，通过share-configs，extension-configs以及spring.config.import。多个属性源加载时机不一致且代码逻辑分叉，**不利于配置模块的扩展**。\n\n出于代码的可维护性考虑，对配置加载逻辑进行了删减，仅保留了spring在Spring Boot 2.4.0 (2020年11月12日)推出的**spring.config.import标准配置导入方式**,在该版本中Spring同时建议**废弃bootstrap模式**启动，统一迁移到**application.properties**。\n\n对于之前通过application.name拼接模式以及share-configs，extension-configs等方式导入的配置，需要**统一修改**为**spring.config.import**模式进行配置导入。\n\n**接入NacosConfig的标准用法如下**\n\n- 导入单个配置\n\n  ```\n  spring:\n  config:\n      import:nacos:application.propertise?refreshEnabled=true&group=DEFAULT_GROUP\n    cloud:\n      nacos:\n        config:\n          serverAddr: {nacos server addr}\n          namespace: {nacos namespace id}\n  ```\n\n- 导入多个配置\n\n  ```\n  spring:\n    config:\n      import:\n        - nacos:application.propertise?group=refreshEnabled=true&group=DEFAULT_GROUP\n        - nacos:{other config data id}?group={other config group}&refreshEnabled=true\n    cloud:\n      nacos:\n        config:\n          serverAddr: {nacos server addr}\n          namespace: {nacos namespace id}\n  ```\n\n#### 应用接入\n\n在启动应用示例进行项目功能演示之前，先了解一下 Spring Cloud 应用如何接入 Nacos Config 作为服务配置中心。\n\n**注意 本章节只是为了便于理解接入方式，本示例代码中已经完成接入工作，无需再进行修改。**\n\n1. 首先，修改 `pom.xml` 文件，引入 spring-cloud-starter-alibaba-nacos-config ；\n\n   ```xml\n   <dependency>\n       <groupId>com.alibaba.cloud</groupId>\n       <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>\n   </dependency>\n   ```\n\n2. 在应用的 `/src/main/resources/application.yaml` 配置文件中配置 Nacos 地址并引入服务配置；\n\n   ```yml\n   spring:\n     cloud:\n       nacos:\n         serverAddr: 127.0.0.1:8848\n         # 以下配置项必须填写\n         username: 'nacos'\n         password: 'nacos'\n     config:\n       import:\n         - nacos:nacos-config-example.properties?refreshEnabled=true&group=DEFAULT_GROUP\n   ```\n\n3. 完成上述两步后，应用会从 Nacos Server 中获取相应的配置，并添加在 Spring Environment 的 PropertySources 中。使用 Nacos 配置中心保存 Nacos 的部分配置时，有以下四种方式:\n   - BeanAutoRefreshConfigExample:  通过将配置信息配置为bean，支持配置变自动刷新的例子；\n   - ConfigListenerExample:         监听配置信息的例子；\n   - DockingInterfaceExample:       对接 Nacos 接口，通过接口完成对配置信息增删改查的例子；\n   - ValueAnnotationExample:        通过 @Value 注解进行配置信息获取的例子。\n\n#### Nacos Server 中添加配置\n\n在命令行执行如下命令，向 Nacos Server 中添加一条配置。**可直接通过 Nacos 控制台注入！**\n\n> **注意：需要替换 accessToken。**\n\n```shell\n$ curl -X POST \"http://127.0.0.1:8848/nacos/v1/cs/configs?accessToken=XXXXXXXXXXXXXXXXXXXXXXXX&dataId=nacos-config-example.properties&group=DEFAULT_GROUP&content=spring.cloud.nacos.config.serverAddr=127.0.0.1:8848%0Aspring.cloud.nacos.config.prefix=PREFIX%0Aspring.cloud.nacos.config.group=GROUP%0Aspring.cloud.nacos.config.namespace=NAMESPACE\"\n```\n\n添加的配置详情如下：\n\n```properties\n# dataId 为 nacos-config-example.properties\n# group 为 DEFAULT_GROUP\n\n# 内容如下:\n\nspring.cloud.nacos.config.serveraddr=127.0.0.1:8848\nspring.cloud.nacos.config.prefix=PREFIX\nspring.cloud.nacos.config.group=GROUP\nspring.cloud.nacos.config.namespace=NAMESPACE\n```\n\n#### 应用启动\n\n1. 增加配置，在应用的 `/src/main/resources/application.yml` 中添加基本配置信息；\n\n   ```yml\n   server:\n     port: 18084\n   management:\n     endpoints:\n       web:\n         exposure:\n           include: '*'\n   ```\n\n2. 启动应用，支持 IDE 直接启动和编译打包后启动。\n\n    1. IDE直接启动：找到主类 `NacosConfigApplication`，执行 main 方法启动应用。\n    2. 打包编译后启动：首先执行 `mvn clean package` 将工程编译打包，进入 `target` 文件夹执行 `java -jar nacos-config-example.jar` 启动应用。\n\n#### 验证\n\n##### 验证自动注入\n\n在浏览器地址栏输入 `http://127.0.0.1:18084/nacos/bean`，并点击调转，可以看到成功从 Nacos Server 中获取了数据。\n\n![get](https://tva1.sinaimg.cn/large/e6c9d24ely1h2gbowleyrj20o40bo753.jpg)\n\n##### 验证动态刷新\n\n1. 执行如下命令，修改 Nacos Server 端的配置数据\n\n   ```shell\n   $ curl -X POST \"http://127.0.0.1:8848/nacos/v1/cs/configs?accessToken=XXXXXXXXXXXXXXXXXXXXXXXXXXX&dataId=nacos-config-example.properties&group=DEFAULT_GROUP&content=spring.cloud.nacos.config.serveraddr=127.0.0.1:8848%0Aspring.cloud.nacos.config.prefix=PREFIX%0Aspring.cloud.nacos.config.group=DEFAULT_GROUP%0Aspring.cloud.nacos.config.namespace=NAMESPACE\"\n   ```\n\n2. 在浏览器地址栏输入 `http://127.0.0.1:18084/nacos/bean`，并点击调转，可以看到应用从 Nacos Server 中获取了最新的数据，group 变成了 DEFAULT_GROUP。\n\n![refresh](https://tva1.sinaimg.cn/large/e6c9d24ely1h2gbpram9rj20nq0ccmxz.jpg)\n\n#### 原理\n\n##### Nacos Config 数据结构\n\nNacos Config 主要通过 dataId 和 group 来唯一确定一条配置，假定您已经了解此背景。如果不了解，请参考 [Nacos 文档](https://nacos.io/zh-cn/docs/concepts.html)。\n\nNacos Client 从 Nacos Server 端获取数据时，调用的是此接口 `ConfigService.getConfig(String dataId, String group, long timeoutMs)`。\n\n##### Spring Cloud 应用获取数据\n\n###### dataID\n\n在 Nacos Config Starter 中，dataId 的拼接格式如下\n\n\t${prefix} - ${spring.profiles.active} . ${file-extension}\n\n* `prefix` 默认为 `spring.application.name` 的值，也可以通过配置项 `spring.cloud.nacos.config.prefix`来配置。\n\n* `spring.profiles.active` 即为当前环境对应的 profile，详情可以参考 [Spring Boot文档](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html#boot-features-profiles)\n\n  **注意，当 active profile 为空时，对应的连接符 `-` 也将不存在，dataId 的拼接格式变成 `${prefix}`.`${file-extension}`**\n\n* `file-extension` 为配置内容的数据格式，可以通过配置项 `spring.cloud.nacos.config.file-extension`来配置。\n  目前只支持 `properties` 类型。\n\n###### group\n* `group` 默认为 `DEFAULT_GROUP`，可以通过 `spring.cloud.nacos.config.group` 配置。\n\n\n##### 自动注入\nSpring Cloud Alibaba Nacos Config Starter 实现了 `org.springframework.boot.context.config.ConfigDataLoader` 接口，并将优先级设置成了最高。\n\n在 Spring Cloud 应用启动阶段，会主动从 Nacos Server 端获取对应的数据，并将获取到的数据转换成 PropertySource 且注入到 Environment 的 PropertySources 属性中，所以使用 @Value 注解也能直接获取 Nacos Server 端配置的内容。\n\n##### 动态刷新\n\nNacos Config Starter 默认为所有获取数据成功的 Nacos 的配置项添加了监听功能，在监听到服务端配置发生变化时会实时触发 `org.springframework.cloud.context.refresh.ContextRefresher` 的 refresh 方法 。\n\n如果需要对 Bean 进行动态刷新，请参照 Spring 和 Spring Cloud 规范。推荐给类添加 `@RefreshScope` 或 `@ConfigurationProperties ` 注解，\n\n更多详情请参考 [ContextRefresher Java Doc](http://static.javadoc.io/org.springframework.cloud/spring-cloud-context/2.0.0.RELEASE/org/springframework/cloud/context/refresh/ContextRefresher.html)。\n\n#### Endpoint 信息查看\n\nSpring Boot 应用支持通过 Endpoint 来暴露相关信息，Spring Cloud Alibaba Nacos Config Starter 也支持这一点。\n\n在使用之前需要在 maven 中添加 `spring-boot-starter-actuator`依赖，并在配置中允许 Endpoints 的访问。\n\nSpring Boot 3.x 可以通过访问 http://127.0.0.1:18084/actuator/nacosconfig 来访问。\n\n![actuator](https://cdn.nlark.com/lark/0/2018/png/54319/1536986344822-279e1edc-ebca-4201-8362-0ddeff240b85.png)\n\n如上图所示，Sources 表示此客户端从哪些 Nacos Config 配置项中获取了信息，RefreshHistory 表示动态刷新的历史记录，最多保存20条，NacosConfigProperties 则为 Nacos Config Starter 本身的配置。\n\n#### More\n\n##### 更多配置项\n配置项|key|默认值|说明\n----|----|-----|-----\n服务端地址|spring.cloud.nacos.config.server-addr||服务器ip和端口\nDataId前缀|spring.cloud.nacos.config.prefix|${spring.application.name}|DataId的前缀，默认值为应用名称\nGroup|spring.cloud.nacos.config.group|DEFAULT_GROUP|\nDataId后缀及内容文件格式|spring.cloud.nacos.config.file-extension|properties|DataId的后缀，同时也是配置内容的文件格式，目前只支持 properties\n配置内容的编码方式|spring.cloud.nacos.config.encode|UTF-8|配置的编码\n获取配置的超时时间|spring.cloud.nacos.config.timeout|3000|单位为 ms\n配置的命名空间|spring.cloud.nacos.config.namespace||常用场景之一是不同环境的配置的区分隔离，例如开发测试环境和生产环境的资源隔离等。\nAccessKey|spring.cloud.nacos.config.access-key||\nSecretKey|spring.cloud.nacos.config.secret-key||\n相对路径|spring.cloud.nacos.config.context-path||服务端 API 的相对路径\n接入点|spring.cloud.nacos.config.endpoint||地域的某个服务的入口域名，通过此域名可以动态地拿到服务端地址\n是否开启监听和自动刷新|spring.cloud.nacos.config.refresh-enabled|true|\n集群服务名|spring.cloud.nacos.config.cluster-name||\n是否开启 Nacos Config 的 Health Indicator|spring.nacos.config.health-indicator.enabled|false|\n是否开启 Nacos Discovery 的 Health Indicator|spring.cloud.nacos.discovery.health-indicator.enabled|false|\n\n\n### Spring Cloud Alibaba Nacos Discovery\n\n#### 如何接入\n\n在启动 Nacos Discovery 示例进行演示之前，了解一下 Spring Cloud 应用如何接入 Nacos Discovery。\n\n**注意 本章节只是为了便于您理解接入方式，本示例代码中已经完成接入工作，您无需再进行修改。**\n\n1. 首先，修改 `pom.xml` 文件，引入 spring-cloud-alibaba-nacos-discovery-starter；\n\n   ```xml\n   <dependency>\n       <groupId>com.alibaba.cloud</groupId>\n       <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n   </dependency>\n   ```\n\n2. 在应用的 `/src/main/resources/application.properties` 配置文件中配置 Nacos Server 地址；\n\n   ```properties\n   spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\n   ```\n\n3. 使用 @EnableDiscoveryClient 注解开启服务注册与发现功能；\n\n   ```java\n   @SpringBootApplication\n   @EnableDiscoveryClient\n   public class ProviderApplication {\n   \n       public static void main(String[] args) {\n           SpringApplication.run(ProviderApplication.class, args);\n       }\n   \n       @RestController\n       class EchoController {\n           @GetMapping(value = \"/echo/{string}\")\n           public String echo(@PathVariable String string) {\n                   return string;\n           }\n       }\n   }\n   ```\n\n#### 应用启动\n\n1. 增加配置，在 nacos-discovery-provider-example 项目的 `/src/main/resources/application.properties` 中添加基本配置信息；\n\n   ```properties\n   spring.application.name=service-provider\n   server.port=18082\n   ```\n\n2. 启动应用，支持 IDE 直接启动和编译打包后启动。\n\n    1. IDE直接启动：找到 nacos-discovery-provider-example 项目的主类 `ProviderApplication`，执行 main 方法启动应用。\n    2. 打包编译后启动：在 nacos-discovery-provider-example 项目中执行 `mvn clean package` 将工程编译打包，然后执行 `java -jar nacos-discovery-provider-example.jar`启动应用。\n\n#### 查询服务验证\n\n> **注意：需要替换 accessToken！**\n\n在浏览器输入此地址 `http://127.0.0.1:8848/nacos/v1/ns/catalog/instances?accessToken=XXXXXXXXXXXXXXXXXXXXXX&serviceName=service-provider&clusterName=DEFAULT&pageSize=10&pageNo=1&namespaceId=`，并点击跳转，可以看到服务节点已经成功注册到 Nacos Server。\n\n![查询服务](https://cdn.nlark.com/lark/0/2018/png/54319/1536986288092-5cf96af9-9a26-466b-85f6-39ad1d92dfdc.png)\n\n#### 服务发现集成 Spring Cloud Loadbalancer\n\n```xml\n<dependencies>\n    <dependency>\n        <groupId>org.springframework.cloud</groupId>\n        <artifactId>spring-cloud-loadbalancer</artifactId>\n    </dependency>\n</dependencies>\n```\n\n增加如下配置，使用 Spring Cloud Alibaba 社区针对 Spring Cloud Loadbalancer 负载均衡依赖提供的负载均衡策略，以便使用 Spring Cloud Alibaba 提供的所有的能力：\n\n```properties\nspring.cloud.loadbalancer.ribbon.enabled=false\nspring.cloud.loadbalancer.nacos.enabled=true\n```\n\n#### IPv4 至 IPv6 地址迁移方案\n\n##### IPv4 和 IPv6 地址双注册\n\n在配置完成 Spring Cloud Loadbalancer 作为负载均衡策略后，应用启动后会默认将微服务的 IPv4 地址和 IPv6 地址注册到注册中心中，其中 IPv4 地址会存放在 Nacos 服务列表中的 IP 字段下，IPv6 地址在 Nacos 的 metadata 字段中，其对应的 Key 为 IPv6。当服务消费者调用服务提供者时，会根据自身的 IP 地址栈支持情况，选择合适的 IP 地址类型发起服务调用。具体规则：\n（1）服务消费者本身支持 IPv4 和 IPv6 双地址栈或仅支持 IPv6 地址栈的情况下，服务消费者会使用服务提供的 IPv6 地址发起服务调用，IPv6 地址调用失败如本身还同时支持 IPv4 地址栈时，暂不支持切换到 IPv4 再发起重试调用；\n（2）服务消费者本身仅支持 IPv4 单地址栈的情况下，服务消费者会使用服务提供的 IPv4 地址发起服务调用。\n\n##### 仅注册 IPv4\n如果您只想使用 IPv4 地址进行注册，可以在 application.properties 使用以下配置：\n\n```properties\nspring.cloud.nacos.discovery.ip-type=IPv4\n```\n\n##### 仅注册 IPv6\n\n如果您只想使用 IPv6 地址，可以在 application.properties 使用以下配置：\n\n```properties\nspring.cloud.nacos.discovery.ip-type=IPv6\n```\n\n#### 使用 RestTemplate 和 FeignClient\n\n下面将分析 nacos-discovery-consumer-example 项目的代码，演示如何 RestTemplate 与 FeignClient。\n\n**注意 本章节只是为了便于理解接入方式，本示例代码中已经完成接入工作，您无需再进行修改。此处只涉及 Ribbon、RestTemplate、FeignClient 相关的内容，如果已经使用了其他服务发现组件，可以通过直接替换依赖来接入 Nacos Discovery。**\n\n1. 添加 @LoadBalanced 注解，使得 RestTemplate 接入 Ribbon\n\n   ```java\n   @Bean\n   @LoadBalanced\n   public RestTemplate restTemplate() {\n      return new RestTemplate();\n   }\n   ```\n\n2. FeignClient 已经默认集成了 Ribbon ，此处演示如何配置一个 FeignClient。\n\n   ```java\n   @FeignClient(name = \"service-provider\")\n   public interface EchoService {\n      @GetMapping(value = \"/echo/{str}\")\n      String echo(@PathVariable(\"str\") String str);\n   }\n   ```\n\n   使用 @FeignClient 注解将 EchoService 这个接口包装成一个 FeignClient，属性 name 对应服务名 service-provider。\n\n   echo 方法上的 @RequestMapping 注解将 echo 方法与 URL \"/echo/{str}\" 相对应，@PathVariable 注解将 URL 路径中的 `{str}` 对应成 echo 方法的参数 str。\n\n3. 完成以上配置后，将两者自动注入到 TestController 中。\n\n   ```java\n   @RestController\n   public class TestController {\n   \n       @Autowired\n       private RestTemplate restTemplate;\n       @Autowired\n       private EchoService echoService;\n   \n       @GetMapping(value = \"/echo-rest/{str}\")\n       public String rest(@PathVariable String str) {\n           return restTemplate.getForObject(\"http://service-provider/echo/\" + str, String.class);\n       }\n       @GetMapping(value = \"/echo-feign/{str}\")\n       public String feign(@PathVariable String str) {\n           return echoService.echo(str);\n       }\n   }\n   ```\n\n4. 配置必要的配置，在 nacos-discovery-consumer-example 项目的 `/src/main/resources/application.properties` 中添加基本配置信息\n\n   ```properties\n\tspring.application.name=service-consumer\n\tserver.port=18083\n\tmanagement.endpoints.web.exposure.include=*\n\tspring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\n\tspring.cloud.nacos.discovery.fail-fast=true\n\t\n\tspring.cloud.nacos.username=nacos\n\tspring.cloud.nacos.password=nacos\n   ```\n\n5.启动应用，支持 IDE 直接启动和编译打包后启动。\n\n1. IDE 直接启动：找到 nacos-discovery-consumer-example 项目的主类 `ConsumerApplication`，执行 main 方法启动应用。\n2. 打包编译后启动：在 nacos-discovery-consumer-example 项目中执行 `mvn clean package` 将工程编译打包，然后执行 `java -jar nacos-discovery-consumer-example.jar` 启动应用。\n\n#### 验证\n\n1. 在浏览器地址栏中输入 [http://127.0.0.1:18083/echo-rest/1234](http://127.0.0.1:18083/echo-rest/1234)，点击跳转，可以看到浏览器显示了 nacos-discovery-provider-example 返回的消息 \"hello Nacos Discovery 1234\"，证明服务发现生效。\n\n![rest](https://cdn.nlark.com/lark/0/2018/png/54319/1536986302124-ee27670d-bdcc-4210-9f5d-875acec6d3ea.png)\n\n2. 在浏览器地址栏中输入 [http://127.0.0.1:18083/echo-feign/12345](http://127.0.0.1:18083/echo-feign/12345)，点击跳转，可以看到浏览器显示 nacos-discovery-provider-example 返回的消息 \"hello Nacos Discovery 12345\"，证明服务发现生效。\n\n![feign](https://cdn.nlark.com/lark/0/2018/png/54319/1536986311685-6d0c1f9b-a453-4ec3-88ab-f7922d210f65.png)\n\n#### 原理\n\n##### 服务注册\n\nSpring Cloud Alibaba Nacos Discovery 遵循了 Spring Cloud Common 标准，实现了 AutoServiceRegistration、ServiceRegistry、Registration 这三个接口。\n\n在 Spring Cloud 应用的启动阶段，监听了 WebServerInitializedEvent 事件，当 Web 容器初始化完成后，即收到 WebServerInitializedEvent 事件后，会触发注册的动作，调用 ServiceRegistry 的 register 方法，将服务注册到 Nacos Server。\n\n#### Endpoint 信息查看\n\nSpring Boot 应用支持通过 Endpoint 来暴露相关信息，Spring Cloud Alibaba Nacos Discovery Starter 也支持这一点。\n\n在使用之前需要在 maven 中添加 `spring-boot-starter-actuator`依赖，并在配置中允许 Endpoints 的访问。\n\nSpring Boot 3.x 可以通过访问 http://127.0.0.1:18083/actuator/nacos-discovery 来访问。\n\n![actuator](https://cdn.nlark.com/lark/0/2018/png/54319/1536986319285-d542dc5f-5dff-462a-9f52-7254776bcd99.png)\n\n如上图所示，NacosDiscoveryProperties 则为 Spring Cloud Alibaba Nacos Discovery 本身的配置，也包括本机注册的内容，subscribe 为本机已订阅的服务信息。\n\n#### More\n\n##### 更多配置项\n\n配置项|key|默认值|说明\n----|----|-----|-----\n服务端地址|spring.cloud.nacos.discovery.server-addr||\n服务名|spring.cloud.nacos.discovery.service|${spring.application.name}|注册到Nacos上的服务名称，默认值为应用名称\n权重|spring.cloud.nacos.discovery.weight|1|取值范围 1 到 100，数值越大，权重越大\n网卡名|spring.cloud.nacos.discovery.network-interface||当IP未配置时，注册的IP为此网卡所对应的IP地址，如果此项也未配置，则默认取第一块网卡的地址\n注册的IP地址|spring.cloud.nacos.discovery.ip||优先级最高\n注册的IP地址类型|spring.cloud.nacos.discovery.ip-type|双栈地址|可以配置IPv4和IPv6两种类型，如果网卡同类型IP地址存在多个，希望制定特定网段地址，可使用`spring.cloud.inetutils.preferred-networks`配置筛选地址\n注册的端口|spring.cloud.nacos.discovery.port|-1|默认情况下不用配置，会自动探测\n命名空间|spring.cloud.nacos.discovery.namespace||常用场景之一是不同环境的注册的区分隔离，例如开发测试环境和生产环境的资源（如配置、服务）隔离等。\nAccessKey|spring.cloud.nacos.discovery.access-key||\nSecretKey|spring.cloud.nacos.discovery.secret-key||\nMetadata|spring.cloud.nacos.discovery.metadata||使用Map格式配置\n日志文件名|spring.cloud.nacos.discovery.log-name||\n集群|spring.cloud.nacos.discovery.cluster-name|DEFAULT|Nacos集群名称\n接入点|spring.cloud.nacos.discovery.endpoint||地域的某个服务的入口域名，通过此域名可以动态地拿到服务端地址\n是否集成LoadBalancer|spring.cloud.loadbalancer.nacos.enabled|false|\n是否开启Nacos Watch|spring.cloud.nacos.discovery.watch.enabled|false|可以设置成true来开启 watch\n是否启用Nacos|spring.cloud.nacos.discovery.enabled|true|默认启动，设置为false时会关闭自动向Nacos注册的功能\n\n### Spring Cloud Alibaba Nacos 集成 Spring Cloud Gateway\n\n#### 如何接入\n\n在启动示例进行演示之前，了解一下 Spring Cloud 应用如何接入 Spring Cloud 如何接入 Nacos Discovery、Spring Cloud Gateway。\n\n**注意 本章节只是为了便于您理解接入方式，本示例代码中已经完成接入工作，您无需再进行修改。**\n\n1. 首先，修改 `pom.xml` 文件，引入 Spring Cloud Alibaba Nacos Discovery Starter、Spring Cloud Gateway Starter。\n\n   ```xml\n   <dependency>\n       <groupId>com.alibaba.cloud</groupId>\n       <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n   </dependency>\n   <dependency>\n       <groupId>org.springframework.cloud</groupId>\n       <artifactId>spring-cloud-starter-gateway-server-webflux</artifactId>\n   </dependency>\n   ```\n\n2. 在应用的 `/src/main/resources/application.properties` 配置文件中配置 Nacos Server 地址\n\n   ```properties\n   spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\n   ```\n\n3. 在应用的 `/src/main/resources/application.properties` 配置文件中配置 Spring Cloud Gateway 路由\n\n   ```properties\n   spring.cloud.gateway.server.webflux.routes[0].id=nacos-route\n   spring.cloud.gateway.server.webflux.routes[0].uri=lb://service-gateway-provider\n   spring.cloud.gateway.server.webflux.routes[0].predicates[0].name=Path\n   spring.cloud.gateway.server.webflux.predicates[0].args[pattern]=/nacos/**\n   spring.cloud.gateway.server.webflux.routes[0].filters[0]=StripPrefix=1\n   ```\n\n4. 使用 @EnableDiscoveryClient 注解开启服务注册与发现功能\n\n   ```java\n   @SpringBootApplication\n   @EnableDiscoveryClient\n   public class GatewayApplication {\n   \n       public static void main(String[] args) {\n           SpringApplication.run(GatewayApplication.class, args);\n       }\n   \n   }\n   ```\n\n#### Spring Cloud Gateway 应用启动\n\n启动应用，支持 IDE 直接启动和编译打包后启动。\n\n1. IDE直接启动：找到 nacos-gateway-discovery-example 项目的主类 `GatewayApplication`，执行 main 方法启动应用。\n2. 打包编译后启动：在 nacos-gateway-discovery-example 项目中执行 `mvn clean package` 将工程编译打包，然后执行 `java -jar nacos-gateway-discovery-example.jar`启动应用。\n\n#### 服务提供方应用启动\n\n启动应用，支持 IDE 直接启动和编译打包后启动。\n\n1. IDE 直接启动：找到 nacos-gateway-provider-example 项目的主类 `ProviderApplication`，执行 main 方法启动应用。\n2. 打包编译后启动：在 nacos-gateway-provider-example 项目中执行 `mvn clean package` 将工程编译打包，然后执行 `java -jar nacos-gateway-provider-example.jar`启动应用。\n\n#### 验证\n\n1.\n\n```bash\n curl 'http://127.0.0.1:18085/nacos/echo/hello-world' \n \n hello Nacos Discovery hello-world⏎\n```\n\n2.\n\n```bash\n curl 'http://127.0.0.1:18085/nacos/divide?a=6&b=2' \n\n 3⏎              \n```\n\n## Native Image构建\n\n请参考 Spring Cloud Alibaba 官网中的 [Graalvm 快速开始](https://sca.aliyun.com/zh-cn/docs/2022.0.0.0/user-guide/graalvm/quick-start)\n\n## 更多介绍\n\nNacos 为用户提供包括动态服务发现，配置管理，服务管理等服务基础设施，帮助用户更灵活，更轻松地构建，交付和管理他们的微服务平台，基于 Nacos, 用户可以更快速的构建以“服务”为中心的现代云原生应用。Nacos 可以和 Spring Cloud、Kubernetes/CNCF、Dubbo 等微服务生态无缝融合，为用户提供更卓越的体验。更多 Nacos 相关的信息，请参考 [Nacos 项目](https://github.com/alibaba/Nacos)。\n\n未来，Spring-Alibaba-Nacos-Config模块将承载更多职责，面向二方中间件组件，对SpringBoot(包括Spring AI)以及SpringCloud应用提供统一的配置托管以及运行时无损轮转功能，面向普通的业务组件，通过@NacosConfig，@NacosConfigListener注解提供灵活易用的配置注入和变更回调能力。\n\n如果您对 Spring Cloud Nacos Discovery 有任何建议或想法，欢迎在 issue 中或者通过其他社区渠道向我们提出。\n\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/nacos-example/readme.md",
    "content": "# Spring Cloud Alibaba Nacos Example\n\n## Project description\n\nThis project demonstrates how to use Spring Cloud Alibaba Nacos related Starters to complete the service discovery and configuration management of Spring Cloud applications.\n\n[Nacos](https://github.com/alibaba/Nacos) It is Alibaba's open source dynamic service discovery, configuration management and service management platform that is easier to build cloud-native applications.\n\n## Nacos Server 3.1.0 is properly configured and started\n\nIn Nacos 3.1.0, functions related to user authentication are added. When starting Nacos Server for the first time, it needs to be configured correctly to avoid the problem of startup failure.\n\n### Download Nacos Server\n\n> The Nacos server version used in this example is 3.1.0!\n\nNacos supports both direct download and source code construction. **Nacos Server version 3.1.0 is recommended for Spring Cloud Alibaba 2022.x.**\n\n1. Direct download: [Nacos Server download page](https://github.com/alibaba/nacos/releases)\n2. Source code construction: Enter Nacos [Github project page](https://github.com/alibaba/nacos), git clone the code to the local compilation and packaging [参考文档](https://nacos.io/zh-cn/docs/quick-start.html).\n\n### Configure the Nacos Server\n\nOpen the `\\nacos-server-3.1.0\\conf\\application.properties` configuration file and modify the following configuration items:\n\n#### Configure the data source\n\nTake the MySQL database as an example here, and use the `nacos-server-3.1.0\\conf\\mysql-schema.sql` initialization database table file. Modify the following configuration as well\n\n```properties\n#*************** Config Module Related Configurations ***************#\n### If use MySQL as datasource:\nspring.datasource.platform=mysql\n\n### Count of DB:\ndb.num=1\n\n### Connect URL of DB:\ndb.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true\ndb.user.0=root\ndb.password.0=root\n\n### Connection pool configuration: hikariCP\ndb.pool.config.connectionTimeout=30000\ndb.pool.config.validationTimeout=10000\ndb.pool.config.maximumPoolSize=20\ndb.pool.config.minimumIdle=2\n```\n\n#### Turn on authentication\n\n**Note: If it is not enabled, login failure exception will occur in 3.1.0!**\n\n```properties\n### The auth system to use, currently only 'nacos' and 'ldap' is supported:\nnacos.core.auth.system.type=nacos\n\n### If turn on auth system:\nnacos.core.auth.enabled=true\n```\n\n#### Set the server authentication key\n\n```properties\nnacos.core.auth.server.identity.key=test\nnacos.core.auth.server.identity.value=test\n```\n\n#### Set the default token\n\n```properties\n### The default token (Base64 String):\nnacos.core.auth.plugin.nacos.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789\n```\n\n** When using the Nacos service discovery and configuration function, be sure to configure `username` and `password` attribute, otherwise the user will not be found! **\n\n#### Open API authentication\n\nAuthentication is required when using the Open api interface in nacos server 3.1.0: For more details, please refer to: [Nacos api authentication](https://nacos.io/zh-cn/docs/auth.html)\n\n1. Obtain accessToken: Use username and password to log in to the nacos server:\n\n   `curl -X POST '127.0.0.1:8848/nacos/v1/auth/login' -d 'username=nacos&password=nacos'`\n\n   If the username and password are correct, the returned information is as follows:\n\n   `{\"accessToken\":\"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYwNTYyOTE2Nn0.2TogGhhr11_vLEjqKko1HJHUJEmsPuCxkur-CfNojDo\", \"tokenTtl\": 18000, \"globalAdmin\": true}`\n\n2. Use accessToken to request the nacos api interface:\n\n   `curl -X GET '127.0.0.1:8848/nacos/v1/cs/configs?accessToken=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYwNTYyMzkyM30.O-s2yWfDSUZ7Svd3Vs7jy9tsfDNHs1SuebJB4KlNY8Q&dataId=nacos.example.1&group=nacos_group'`\n\n### Start the Nacos Server\n\n1. Start Nacos Server, enter the folder after downloading to the local and decompressing (enter the folder after compiling and packaging by using the source code construction method), then enter its relative folder `nacos/bin`, and execute the following command according to the actual situation of the operating system. [详情参考此文档](https://nacos.io/zh-cn/docs/quick-start.html)。\n\n   1. Linux/Unix/Mac operating system, execute the command\n\n       `sh startup.sh -m standalone`\n\n   2. Windows operating system, executing command\n\n       `cmd startup.cmd`\n\n2. Access Nacos Server Console.\n\n   The browser enters the address http://127.0.0.1:8848/nacos , **The first login needs to bind the nacos user, because the new version adds authentication, and the user name and password need to be configured during application registration and configuration binding.**\n\n## Nacos application example\n\n### Spring Cloud Alibaba Nacos Config\n\n#### Configuration Update Instructions\n\nIn version 2023.0.1.3, to support integration with Nacos Configuration Center in Spring Boot applications and to enable annotations such as `@NacosConfig` and `@NacosConfigListener` based on the original `nacos config` module, the `spring-cloud-starter-alibaba-nacos-config` module has been split into two:\n\n- **spring-alibaba-nacos-config**: Depends only on Spring Boot and can be used independently in non-Spring Cloud applications.\n- **spring-cloud-starter-alibaba-nacos-config**: Retains only the components that depend on Spring Cloud.\n\nDuring the module refactoring, it was observed that as the code evolved, multiple branches of configuration loading logic emerged. This includes the original approach of concatenating `spring.application.name` with `fileExtension` and loading configurations via `share-configs`, `extension-configs`, and `spring.config.import`. These different property sources were loaded at inconsistent times, resulting in **fragmented logic that hinders the extensibility of the configuration module**.\n\nTo improve code maintainability, the configuration loading logic has been streamlined, retaining only the **`spring.config.import` standard configuration import mechanism**, which was introduced in **Spring Boot 2.4.0 (November 12, 2020)**. In that release, Spring also **recommended deprecating the bootstrap mode** and encouraged unifying configuration into **`application.properties`**.\n\nFor configurations previously loaded using the `application.name` concatenation approach or via `share-configs`, `extension-configs`, etc., you now need to **migrate to using the `spring.config.import`** mechanism for configuration import.\n\n**The standard usage for integrating with NacosConfig is as follows**:\n\n- Importing a Single Configuration\n\n  ```\n  spring:\n  config:\n      import:nacos:application.propertise?refreshEnabled=true&group=DEFAULT_GROUP\n    cloud:\n      nacos:\n        config:\n          serverAddr: {nacos server addr}\n          namespace: {nacos namespace id}\n  ```\n\n- Importing Multiple Configurations\n\n  ```\n  spring:\n    config:\n      import:\n        - nacos:application.propertise?group=refreshEnabled=true&group=DEFAULT_GROUP\n        - nacos:{other config data id}?group={other config group}&refreshEnabled=true\n    cloud:\n      nacos:\n        config:\n          serverAddr: {nacos server addr}\n          namespace: {nacos namespace id}\n  ```\n\n#### Application access\n\nBefore starting the application sample to demonstrate the project function, first understand how the Spring Cloud application accesses Nacos Config as the service configuration center.\n\n**Note that this section is only for the convenience of understanding the access method. The access work has been completed in this sample code, and no further modification is required.**\n\n1. First, modify the `pom.xml` file to introduce spring-cloud-starter-alibaba-nacos-config;\n\n   ```xml\n   <dependency>\n       <groupId>com.alibaba.cloud</groupId>\n       <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>\n   </dependency>\n   ```\n\n2. Configuring a Nacos address in an `/src/main/resources/application.yaml` applied configuration file and introducing a service configuration;\n\n   ```yml\n   spring:\n     cloud:\n       nacos:\n         serverAddr: 127.0.0.1:8848\n         username: 'nacos'\n         password: 'nacos'\n     config:\n       import:\n         - nacos:nacos-config-example.properties?refreshEnabled=true&group=DEFAULT_GROUP\n   ```\n\n3. After completing the above two steps, the application will obtain the corresponding configuration from Nacos Server and add it to the Property Sources of Spring Environment. There are four ways to save a portion of the Nacos configuration using the Nacos Configuration Center:\n   - BeanAutoRefres hConfig Example: An example of supporting automatic refresh of configuration changes by configuring configuration information as beans;\n   - ConfigListenerEx ample: example of monitoring configuration information;\n   - Docking Interface Example: An example of docking the Nacos interface and completing the addition, deletion, modification and query of the configuration information through the interface;\n   - ValueAnnotation Example: An example of obtaining configuration information through the @ Value annotation.\n\n#### Add Configuration in Nacos Server\n\nAdd a configuration to the Nacos Server by executing the following command from the command line. **Can be injected directly through the Nacos console!**\n\n```shell\n$ curl -X POST \"http://127.0.0.1:8848/nacos/v1/cs/configs?accessToken=XXXXXXXXXXXXXXXXXXXXXXXXXXX&dataId=nacos-config-example.properties&group=DEFAULT_GROUP&content=spring.cloud.nacos.config.serverAddr=127.0.0.1:8848%0Aspring.cloud.nacos.config.prefix=PREFIX%0Aspring.cloud.nacos.config.group=GROUP%0Aspring.cloud.nacos.config.namespace=NAMESPACE\"\n```\n\nDetails of the added configuration are as follows:\n\n```properties\n# dataId is nacos-config-example.properties\n# group is DEFAULT_GROUP\n\n# content is:\n\nspring.cloud.nacos.config.serveraddr=127.0.0.1:8848\nspring.cloud.nacos.config.prefix=PREFIX\nspring.cloud.nacos.config.group=GROUP\nspring.cloud.nacos.config.namespace=NAMESPACE\n```\n\n#### The application starts\n\n1. Add configuration, and add basic configuration information in the application `/src/main/resources/application.yml`;\n\n   ```yml\n   server:\n     port: 18084\n   management:\n     endpoints:\n       web:\n         exposure:\n           include: '*'\n   ```\n\n2. Start the application, support IDE direct start and start after compilation and packaging.\n\n    1. IDE direct startup: find the main class `NacosConfigApplication` and execute the main method to start the application.\n    2. Start after packaging and compiling: First `mvn clean package`, compile and package the project, and then enter the `target` folder to `java -jar nacos-config-example.jar` start the application.\n\n#### Validate\n\n##### Verify automatic injection\n\nEnter `http://127.0.0.1:18084/nacos/bean` in the browser address bar and click turn around to see that the data is successfully obtained from the Nacos Server.\n\n![get](https://tva1.sinaimg.cn/large/e6c9d24ely1h2gbowleyrj20o40bo753.jpg)\n\n##### Verify dynamic refresh\n\n1. Execute the following command to modify the configuration data on the Nacos Server side\n\n   ```shell\n   $ curl -X POST \"http://127.0.0.1:8848/nacos/v1/cs/configs?accessToken=XXXXXXXXXXXXXXXXXXXXXXXXXXX&dataId=nacos-config-example.properties&group=DEFAULT_GROUP&content=spring.cloud.nacos.config.serveraddr=127.0.0.1:8848%0Aspring.cloud.nacos.config.prefix=PREFIX%0Aspring.cloud.nacos.config.group=DEFAULT_GROUP%0Aspring.cloud.nacos.config.namespace=NAMESPACE\"\n   ```\n\n2. Type `http://127.0.0.1:18084/nacos/bean` in the address bar of the browser and click Turn, and you can see that the application obtains the latest data from the Nacos Server, and the group becomes the DEFAULT _ GROUP.\n\n![refresh](https://tva1.sinaimg.cn/large/e6c9d24ely1h2gbpram9rj20nq0ccmxz.jpg)\n\n#### Principle\n\n##### Nacos Config Data Structure\n\nNacos Config uniquely identifies a piece of configuration primarily by dataId and group, assuming you already know this background. If you don't know, please refer to [Nacos 文档](https://nacos.io/zh-cn/docs/concepts.html).\n\nWhen the Nacos Client obtains data from the Nacos Server, it calls this interface `ConfigService.getConfig(String dataId, String group, long timeoutMs)`.\n\n##### Spring Cloud App Get Data\n\n###### dataID\n\nIn the Nacos Config Starter, the concatenation format of dataId is as follow\n\n\t${prefix} - ${spring.profiles.active} . ${file-extension}\n\n* The `prefix` default value is `spring.application.name`. It can also be configured through configuration items `spring.cloud.nacos.config.prefix`.\n\n*  `spring.profiles.active` This is the profile corresponding to the current environment. For details, please refer to\n\n  ** Note that when the active profile is empty, the corresponding connector `-` does not exist, and the concatenation format of dataId becomes `${prefix}`. `${file-extension}` **\n\n*  `file-extension` It is used to configure the data format of content, which can be configured by configuration item `spring.cloud.nacos.config.file-extension`. Currently only types are supported `properties`.\n\n###### group\n*  `group` The default is `DEFAULT_GROUP`, which can be `spring.cloud.nacos.config.group` configured.\n\n\n##### Automatic injection\nThe Spring Cloud Alibaba Nacos Config Starter implements the `org.springframework.boot.context.config.ConfigDataLoader` interface and sets the priority to the highest.\n\nDuring the Spring Cloud application startup phase, it will actively obtain the corresponding data from the Nacos Server side, convert the obtained data into PropertySource, and inject it into the Property Sources attribute of the Environment. Therefore, the @ Value annotation can also be used to directly obtain the contents of the Nacos Server configuration.\n\n##### Dynamic refresh\n\nBy default, the Nacos Config Starter is a refresh method that is triggered `org.springframework.cloud.context.refresh.ContextRefresher` in real time when the monitoring function is added to the configuration item of all Nacos that have successfully obtained data and changes in the server configuration are monitored.\n\nIf you need to refresh the Bean dynamically, refer to the Spring and Spring Cloud specifications. It is recommended that you add `@RefreshScope` or `@ConfigurationProperties ` annotate the class,\n\nFor more details, please refer to [ContextRefresher Java Doc](http://static.javadoc.io/org.springframework.cloud/spring-cloud-context/2.0.0.RELEASE/org/springframework/cloud/context/refresh/ContextRefresher.html).\n\n#### Endpoint information viewing\n\nSpring Boot applications support the use of Endpoints to expose relevant information, as does the Spring Cloud Alibaba Nacos Config Starter.\n\nBefore using it, you need to add `spring-boot-starter-actuator` a dependency in Maven and allow Endpoints access in the configuration.\n\nSpring Boot 3.x can be accessed by visiting http://127.0.0.1:18084/actuator/nacosconfig .\n\n![actuator](https://cdn.nlark.com/lark/0/2018/png/54319/1536986344822-279e1edc-ebca-4201-8362-0ddeff240b85.png)\n\nAs shown in the figure above, Sources indicates which Nacos Config configuration items the client has obtained information from, and RefreshHistory indicates the history of dynamic refresh, with a maximum of 20 entries saved. NacosConfig Properties is the configuration of the Nacos Config Starter itself.\n\n#### More\n\n##### More configuration items\nConfiguration item | key | Default value | Description\n----|----|-----|-----\nServer address | spring. Cloud. Nacos. Config. Server-addr | | server IP and port\nPrefix of DataId | spring. Cloud. Nacos. Config. Prefix | ${ spring. Application. Name } | Prefix of DataId. The default value is the application name\nGroup|spring.cloud.nacos.config.group|DEFAULT_GROUP|\nSuffix of DataId and content file format | spring. Cloud. Nacos. Config. File -extension | properties | Suffix of DataId, which is also the file format of configuration content. Currently, only properties is supported\nEncoding method of the configured content | spring. Cloud. Nacos. Config. Encode | UTF-8 | Configured encoding\n| Obtain the configured timeout | spring. Cloud. Nacos. Config. Timeout | 3000 | Unit: ms |\nNamespace of configuration | spring. Cloud. Nacos. Config. Namespace | | One of the common scenarios is to distinguish and isolate the configurations of different environments, such as the resource isolation between the development and testing environments and the production environment.\nAccessKey|spring.cloud.nacos.config.access-key||\nSecretKey|spring.cloud.nacos.config.secret-key||\nRelative path | spring. Cloud. Nacos. Config. Context-path | | Relative path of the server API\nAccess point | spring. Cloud. Nacos. Config. Endpoint | | The domain name of a service in a region. The server address can be obtained dynamically through this domain name\nWhether to enable listening and automatic refresh | spring. Cloud. Nacos. Config. Refresh -enabled | true |\nCluster service name | spring. Cloud. Nacos. Config. Cluster -name | |\nWhether to enable nacos-config health indicator |spring.nacos.config.health-indicator.enabled|false|\nWhether to enable nacos-discovery health indicator |spring.cloud.nacos.discovery.health-indicator.enabled|false|\n\n### Spring Cloud Alibaba Nacos Discovery\n\n#### How to access\n\nBefore launching the Nacos Discovery sample for demonstration, take a look at how Spring Cloud applications access Nacos Discovery.\n\n**Note that this section is only for your convenience to understand the access method. The access work has been completed in this sample code, and you do not need to modify it.**\n\n1. First, modify the `pom.xml` file and introduce spring-cloud-alibaba-nacos-discovery-starter;\n\n   ```xml\n   <dependency>\n       <groupId>com.alibaba.cloud</groupId>\n       <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n   </dependency>\n   ```\n\n2. Configuring a Nacos Server address in an `/src/main/resources/application.properties` applied configuration file;\n\n   ```properties\n   spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\n   ```\n\n3. Use @ EnableDiscoveryClient annotation to enable service registration and discovery;\n\n   ```java\n   @SpringBootApplication\n   @EnableDiscoveryClient\n   public class ProviderApplication {\n   \n       public static void main(String[] args) {\n           SpringApplication.run(ProviderApplication.class, args);\n       }\n   \n       @RestController\n       class EchoController {\n           @GetMapping(value = \"/echo/{string}\")\n           public String echo(@PathVariable String string) {\n                   return string;\n           }\n       }\n   }\n   ```\n\n#### The application starts\n\n1. Add the configuration, and add the basic configuration information in the nacos-discovery-provider-example project `/src/main/resources/application.properties`;\n\n   ```properties\n   spring.application.name=service-provider\n   server.port=18082\n   ```\n\n2. Start the application, support IDE direct start and start after compilation and packaging.\n\n    1. IDE direct startup: Find the main class `ProviderApplication` of the nacos-discovery-provider-example project, and execute the main method to start the application.\n    2. Start after compilation: Compile and package `mvn clean package` the project in the nacos-discovery-provider-example project, and then `java -jar nacos-discovery-provider-example.jar` start the application.\n\n#### Query service validation\n\nEnter this address `http://127.0.0.1:8848/nacos/v1/ns/catalog/instances?accessToken=XXXXXXXXXXXXXXXXXXXXXXXXXXX&serviceName=service-provider&clusterName=DEFAULT&pageSize=10&pageNo=1&namespaceId=` in the browser and click Jump to see that the service node has been successfully registered to the Nacos Server.\n\n![查询服务](https://cdn.nlark.com/lark/0/2018/png/54319/1536986288092-5cf96af9-9a26-466b-85f6-39ad1d92dfdc.png)\n\n#### Service discovery integration Spring Cloud Loadbalancer.\n\n```xml\n<dependencies>\n    <dependency>\n        <groupId>org.springframework.cloud</groupId>\n        <artifactId>spring-cloud-loadbalancer</artifactId>\n    </dependency>\n</dependencies>\n```\n\nAdd the following configuration to use the load balancing strategy provided by the Spring Cloud Alibaba community for Spring Cloud Loadbalancer load balancing dependencies, so as to use all the capabilities provided by the Spring Cloud Alibaba:\n\n```properties\nspring.cloud.loadbalancer.ribbon.enabled=false\nspring.cloud.loadbalancer.nacos.enabled=true\n```\n\n#### IPv4 to IPv6 address migration schema\n\n##### Dual registration of IPv4 and IPv6 addresses\n\nAfter configuring the Spring Cloud Loadbalancer as a load balancing strategy, the application will register the IPv4 address and IPv6 address of the microservice in the registration center by default after starting, where the IPv4 address will be stored under the IP field in the Nacos service list. The IPv6 address is in the metadata field of Nacos, and its corresponding Key is IPv6. When the service consumer calls the service provider, it will select the appropriate IP address type to initiate the service call according to its own IP address stack support. Specific rules: (1) If the service consumer itself supports both IPv4 and IPv6 address stacks or only supports IPv6 address stacks, the service consumer will use the IPv6 address provided by the service to initiate a service call. If the IPv6 address call fails, if it also supports IPv4 address stacks, (2) When the service consumer itself only supports IPv4 single address stack, the service consumer will use the IPv4 address provided by the service to initiate a service call.\n\n##### Register IPv4 only\nIf you want to register using only IPv4 addresses, you can use the following configuration at the application. Properties:\n\n```properties\nspring.cloud.nacos.discovery.ip-type=IPv4\n```\n\n##### Register for IPv6 only\n\nIf you want to use only IPv6 addresses, you can use the following configuration on the application. Properties:\n\n```properties\nspring.cloud.nacos.discovery.ip-type=IPv6\n```\n\n#### Using RestTemplate and FeignClient\n\nHere's a look at the code for the nacos-discovery-consumer-example project to show how to RestTemplate and FeignClient.\n\n**Note that this section is only for the convenience of understanding the access method. The access work has been completed in this sample code, and you do not need to modify it. Only Ribbon, RestTemplate and FeignClient are involved here. If other service discovery components have been used, Nacos Discovery can be accessed by directly replacing dependencies.**\n\n1. Add the @ LoadBalanced annotation to make the RestTemplate access the Ribbon\n\n   ```java\n   @Bean\n   @LoadBalanced\n   public RestTemplate restTemplate() {\n      return new RestTemplate();\n   }\n   ```\n\n2. FeignClient has been integrated with Ribbon by default. Here is how to configure a FeignClient.\n\n   ```java\n   @FeignClient(name = \"service-provider\")\n   public interface EchoService {\n      @GetMapping(value = \"/echo/{str}\")\n      String echo(@PathVariable(\"str\") String str);\n   }\n   ```\n\n   Use the @ FeignClient annotation to wrap the Echo Service interface as a FeignClient, and the attribute name corresponds to the service name service-provider.\n\n   The @ RequestMapping annotation on the echo method corresponds the echo method to the URL \"/echo/{ str}\", and the @ PathVariable annotation corresponds the str in `{str}` the URL path to the parameter of the echo method.\n\n3. After the above configuration is completed, the two are automatically injected into the TestController.\n\n   ```java\n   @RestController\n   public class TestController {\n   \n       @Autowired\n       private RestTemplate restTemplate;\n       @Autowired\n       private EchoService echoService;\n   \n       @GetMapping(value = \"/echo-rest/{str}\")\n       public String rest(@PathVariable String str) {\n           return restTemplate.getForObject(\"http://service-provider/echo/\" + str, String.class);\n       }\n       @GetMapping(value = \"/echo-feign/{str}\")\n       public String feign(@PathVariable String str) {\n           return echoService.echo(str);\n       }\n   }\n   ```\n\n4. Configure the necessary configuration and add the basic configuration information in the nacos-discovery-consumer-example project `/src/main/resources/application.properties`.\n\n   ```java\n   @RestController\n   public class TestController {\n   \n       @Autowired\n       private RestTemplate restTemplate;\n       @Autowired\n       private EchoService echoService;\n   \n       @GetMapping(value = \"/echo-rest/{str}\")\n       public String rest(@PathVariable String str) {\n           return restTemplate.getForObject(\"http://service-provider/echo/\" + str, String.class);\n       }\n       @GetMapping(value = \"/echo-feign/{str}\")\n       public String feign(@PathVariable String str) {\n           return echoService.echo(str);\n       }\n   }\n   ```\n\n5.Start the application, support IDE direct start and start after compilation and packaging.\n\n1. IDE direct startup: Find the main class `ConsumerApplication` of the nacos-discovery-consumer-example project, and execute the main method to start the application.\n2. Start after compilation: Compile and package `mvn clean package` the project in the nacos-discovery-consumer-example project, and then `java -jar nacos-discovery-consumer-example.jar` start the application.\n\n#### Validate\n\n1. Enter [http://127.0.0.1:18083/echo-rest/1234](http://127.0.0.1:18083/echo-rest/1234) and click Go, you can see that the message \"hello Nacos Discovery 1234\" returned by nacos-discovery-provider-example in the browser address bar to prove that the service discovery is valid.\n\n![rest](https://cdn.nlark.com/lark/0/2018/png/54319/1536986302124-ee27670d-bdcc-4210-9f5d-875acec6d3ea.png)\n\n2. Enter [http://127.0.0.1:18083/echo-feign/12345](http://127.0.0.1:18083/echo-feign/12345) and click Go, you can see that the message \"hello Nacos Discovery 12345\" returned by nacos-discovery-provider-example in the browser address bar to prove that the service discovery is effective.\n\n![feign](https://cdn.nlark.com/lark/0/2018/png/54319/1536986311685-6d0c1f9b-a453-4ec3-88ab-f7922d210f65.png)\n\n#### Principle\n\n##### Service registration\n\nThe Spring Cloud Alibaba Nacos Discovery follows the Spring cloud Common standard. The three interfaces of AutoService Registration, Service Registry and Registration are implemented.\n\nIn the startup phase of the Spring Cloud application, the WebServerInitializedEvent event is monitored. After the Web container is initialized, that is, after the WebServerInitializedEvent event is received, the registration action is triggered. Call the register method of the Service Registry to register the service with the Nacos Server.\n\n#### Endpoint information viewing\n\nSpring Boot applications support the use of Endpoints to expose relevant information, as does the Spring Cloud Alibaba Nacos Discovery Starter.\n\nBefore using it, you need to add `spring-boot-starter-actuator` a dependency in Maven and allow Endpoints access in the configuration.\n\nSpring Boot 3.x can be accessed by visiting http://127.0.0.1:18083/actuator/nacos-discovery .\n\n![actuator](https://cdn.nlark.com/lark/0/2018/png/54319/1536986319285-d542dc5f-5dff-462a-9f52-7254776bcd99.png)\n\nAs shown in the figure above, NacosDiscovery Properties refers to the configuration of the Spring Cloud Alibaba Nacos Discovery itself, including the content registered by the local machine, and subscribe refers to the subscribed service information of the local machine.\n\n#### More\n\n##### More configuration items\n\nConfiguration item | key | Default value | Description\n----|----|-----|-----\nServer address | spring. Cloud. Nacos. Discovery. Server -addr | |\nService Name | spring. Cloud. Nacos. Discovery. Service | ${ spring. Application. Name } | The name of the service registered to Nacos. The default is the application name\nWeight | spring. Cloud. Nacos. Discovery. Weight | 1 | Values range from 1 to 100. The larger the value, the greater the weight\nNetwork card name | spring. Cloud. Nacos. Discovery. Network -interface | | When IP is not configured, the registered IP is the IP address corresponding to this network card. If this item is not configured, the address of the first network card is used by default\nRegistered IP Address | spring. Cloud. Nacos. Discovery. IP | | Highest Priority\nRegistered IP address type | spring. Cloud. Nacos. Discovery. IP -type | Dual stack address | Both IPv4 and IPv6 types can be configured. If there are multiple IP addresses of the same type in the network card and you want to designate a specific network segment address, you can configure the filtering address with `spring.cloud.inetutils.preferred-networks`\nRegistered port | spring. Cloud. Nacos. Discovery. Port | -1 | is not configured by default and will be detected automatically\nNamespace | spring. Cloud. Nacos. Discovery. Namespace | | One of the common scenarios is to distinguish and isolate the registration of different environments, such as the isolation of resources (such as configurations and services) between the development and testing environments and the production environment.\nAccessKey|spring.cloud.nacos.discovery.access-key||\nSecretKey|spring.cloud.nacos.discovery.secret-key||\nMetadata | spring. Cloud. Nacos. Discovery. Metadata | | Configure using Map format\nLog file name | spring. Cloud. Nacos. Discovery. Log -name | |\nCluster | spring. Cloud. Nacos. Discovery. Cluster -name | DEFAULT | Nacos cluster name\nAccess point | spring. Cloud. Nacos. Discovery. Endpoint | | The domain name of a service in a region. The server address can be obtained dynamically through this domain name\nIntegrate LoadBalancer | spring. Cloud. Loadbalancer. Nacos. Enabled | false |\nNacos Watch enabled | spring. Cloud. Nacos. Discovery. Watch. Enabled | false | can be set to true to enable watch\nEnable Nacos | spring. Cloud. Nacos. Discovery. Enabled | true | Start by default. If set to false, automatic registration with Nacos will be disabled\n\n### Spring Cloud Alibaba Nacos integrated Spring Cloud Gateway.\n\n#### How to access\n\nBefore starting the demo, learn how Spring Cloud applications connect to Spring Cloud, Nacos Discovery, and Spring Cloud Gateway.\n\n**Note that this section is only for your convenience to understand the access method. The access work has been completed in this sample code, and you do not need to modify it.**\n\n1. First, modify the `pom.xml` file to introduce Spring Cloud Alibaba Nacos Discovery Starter and Spring Cloud Gateway Starter.\n\n   ```xml\n   <dependency>\n       <groupId>com.alibaba.cloud</groupId>\n       <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n   </dependency>\n   <dependency>\n       <groupId>org.springframework.cloud</groupId>\n       <artifactId>spring-cloud-starter-gateway-server-webflux</artifactId>\n   </dependency>\n   ```\n\n2. Configure the Nacos Server address in the applied `/src/main/resources/application.properties` configuration films\n\n   ```properties\n   spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\n   ```\n\n3. Configure Spring Cloud Gateway routing in the application's `/src/main/resources/application.properties` configuration file\n\n   ```properties\n   spring.cloud.gateway.server.webflux.routes[0].id=nacos-route\n   spring.cloud.gateway.server.webflux.routes[0].uri=lb://service-gateway-provider\n   spring.cloud.gateway.server.webflux.routes[0].predicates[0].name=Path\n   spring.cloud.gateway.server.webflux.routes[0].predicates[0].args[pattern]=/nacos/**\n   spring.cloud.gateway.server.webflux.routes[0].filters[0]=StripPrefix=1\n   ```\n\n4. Use the @ EnableDiscoveryClient annotation to turn on service registration and discovery\n\n   ```java\n   @SpringBootApplication\n   @EnableDiscoveryClient\n   public class GatewayApplication {\n   \n       public static void main(String[] args) {\n           SpringApplication.run(GatewayApplication.class, args);\n       }\n   \n   }\n   ```\n\n#### Spring Cloud Gateway App Launch\n\nStart the application, support IDE direct start and start after compilation and packaging.\n\n1. IDE direct startup: Find the main class `GatewayApplication` of the nacos-gateway-discovery-example project, and execute the main method to start the application.\n2. Start after compilation: Compile and package `mvn clean package` the project in the nacos-gateway-discovery-example project, and then `java -jar nacos-gateway-discovery-example.jar` start the application.\n\n#### Service Provider Application Launch\n\nStart the application, support IDE direct start and start after compilation and packaging.\n\n1. Start the IDE directly: find the main class `ProviderApplication` of the nacos-gateway-provider-example project, and execute the main method to start the application.\n2. Start after compilation: Compile and package `mvn clean package` the project in the nacos-gateway-provider-example project, and then `java -jar nacos-gateway-provider-example.jar` start the application.\n\n#### Validate\n\n1.\n\n```bash\n curl 'http://127.0.0.1:18085/nacos/echo/hello-world' \n \n hello Nacos Discovery hello-world⏎\n```\n\n2.\n\n```bash\n curl 'http://127.0.0.1:18085/nacos/divide?a=6&b=2' \n\n 3⏎              \n```\n\n## Native Image build\n\nPlease refer to the Spring Cloud Alibaba website\n\n## More introduction\n\nNacos provides users with service infrastructure including dynamic service discovery, configuration management, service management, etc., to help users build, deliver and manage their microservice platforms more flexibly and easily. Based on Nacos, users can build modern cloud native applications centered on \"services\" more quickly. Nacos can be seamlessly integrated with Spring Cloud, Kubernetes/CNCF, Dubbo and other micro-service ecosystems to provide users with a better experience. For more information about Nacos, see the [Nacos 项目](https://github.com/alibaba/Nacos).\n\nIn the future, the **Spring-Alibaba-Nacos-Config** module will take on more responsibilities. It will serve as a unified configuration management solution for both second-party middleware components and business components. For **Spring Boot** (including **Spring AI**) and **Spring Cloud** applications, it will provide centralized configuration hosting and seamless runtime configuration rotation. For general business components, it will offer flexible and user-friendly configuration injection and change callback capabilities through the `@NacosConfig` and `@NacosConfigListener` annotations.\n\nIf you have any suggestions or ideas about Spring Cloud Nacos Discovery, please feel free to send them to us in the issue or through other community channels.\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>spring-cloud-alibaba-examples</artifactId>\n    <packaging>pom</packaging>\n    <name>Spring Cloud Alibaba Examples</name>\n    <description>Example showing how to use features of Spring Cloud Alibaba</description>\n\n    <modules>\n        <module>sentinel-example/sentinel-core-example</module>\n        <module>sentinel-example/sentinel-openfeign-example</module>\n        <module>sentinel-example/sentinel-resttemplate-example</module>\n        <module>sentinel-example/sentinel-circuitbreaker-example</module>\n        <module>sentinel-example/sentinel-webflux-example</module>\n        <module>sentinel-example/sentinel-spring-cloud-gateway-example</module>\n        <module>nacos-example/nacos-discovery-example</module>\n        <module>nacos-example/nacos-config-example</module>\n        <module>nacos-example/nacos-gateway-example</module>\n        <module>seata-example/business-service</module>\n        <module>seata-example/order-service</module>\n        <module>seata-example/storage-service</module>\n        <module>seata-example/account-service</module>\n        <module>rocketmq-example/rocketmq-comprehensive-example</module>\n        <module>rocketmq-example/rocketmq-orderly-consume-example</module>\n        <module>rocketmq-example/rocketmq-broadcast-example/rocketmq-broadcast-producer-example</module>\n        <module>rocketmq-example/rocketmq-broadcast-example/rocketmq-broadcast-consumer1-example</module>\n        <module>rocketmq-example/rocketmq-broadcast-example/rocketmq-broadcast-consumer2-example</module>\n        <module>rocketmq-example/rocketmq-delay-consume-example</module>\n        <module>rocketmq-example/rocketmq-sql-consume-example</module>\n        <module>rocketmq-example/rocketmq-example-common</module>\n        <module>rocketmq-example/rocketmq-tx-example</module>\n        <module>rocketmq-example/rocketmq-pollable-consume-example</module>\n        <module>spring-cloud-bus-rocketmq-example</module>\n        <module>spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-nacos-example</module>\n        <module>spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-consul-example</module>\n        <module>integrated-example/integrated-storage</module>\n        <module>integrated-example/integrated-account</module>\n        <module>integrated-example/integrated-order</module>\n        <module>integrated-example/integrated-gateway</module>\n        <module>integrated-example/integrated-praise-provider</module>\n        <module>integrated-example/integrated-praise-consumer</module>\n        <module>integrated-example/integrated-common</module>\n\t\t<module>integrated-example/integrated-frontend</module>\n        <module>spring-cloud-scheduling-example</module>\n    </modules>\n\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n            <plugin>\n                <groupId>org.graalvm.buildtools</groupId>\n                <artifactId>native-maven-plugin</artifactId>\n                <version>${native-maven-plugin.version}</version>\n            </plugin>\n\n            <!--Exclude javadoc jars-->\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-javadoc-plugin</artifactId>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n\n            <!--Exclude sources jars-->\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-source-plugin</artifactId>\n                <configuration>\n                    <skipSource>true</skipSource>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n    <profiles>\n        <profile>\n            <id>native</id>\n            <build>\n                <pluginManagement>\n                    <plugins>\n                        <plugin>\n                            <groupId>org.springframework.boot</groupId>\n                            <artifactId>spring-boot-maven-plugin</artifactId>\n                            <configuration>\n                                <jvmArguments>\n                                    -agentlib:native-image-agent=config-merge-dir=src/main/resources/META-INF/native-image/\n                                </jvmArguments>\n                                <image>\n                                    <builder>paketobuildpacks/builder:tiny</builder>\n                                    <env>\n                                        <BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>\n                                    </env>\n                                </image>\n                            </configuration>\n                            <executions>\n                                <execution>\n                                    <id>process-aot</id>\n                                    <goals>\n                                        <goal>process-aot</goal>\n                                    </goals>\n                                </execution>\n                            </executions>\n                        </plugin>\n                        <plugin>\n                            <groupId>org.graalvm.buildtools</groupId>\n                            <artifactId>native-maven-plugin</artifactId>\n                            <configuration>\n                                <classesDirectory>${project.build.outputDirectory}</classesDirectory>\n                                <metadataRepository>\n                                    <enabled>true</enabled>\n                                </metadataRepository>\n                                <requiredVersion>22.3</requiredVersion>\n                            </configuration>\n                            <executions>\n                                <execution>\n                                    <id>add-reachability-metadata</id>\n                                    <goals>\n                                        <goal>add-reachability-metadata</goal>\n                                    </goals>\n                                </execution>\n                            </executions>\n                        </plugin>\n                    </plugins>\n                </pluginManagement>\n            </build>\n        </profile>\n    </profiles>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/readme-zh.md",
    "content": "# RocketMQ Example\n\n## 项目说明\n\n本项目演示如何使用 RocketMQ Binder 完成 Spring Cloud 应用消息的订阅和发布。\n\n[RocketMQ](https://rocketmq.apache.org/) 是一款开源的分布式消息系统，基于高可用分布式集群技术，提供低延时的、高可靠的消息发布与订阅服务。\n\n在说明 RocketMQ 的示例之前，我们先了解一下 Spring Cloud Stream。\n\n这是官方对 Spring Cloud Stream 的一段介绍：\n\nSpring Cloud Stream 是一个用于构建基于消息的微服务应用框架。它基于 SpringBoot 来创建具有生产级别的单机 Spring 应用，并且使用 `Spring Integration` 与 Broker 进行连接。\n\nSpring Cloud Stream 提供了消息中间件配置的统一抽象，推出了 publish-subscribe、consumer groups、partition 这些统一的概念。\n\nSpring Cloud Stream 内部有两个概念：Binder 和 Binding。\n\n* Binder: 跟外部消息中间件集成的组件，用来创建 Binding，各消息中间件都有自己的 Binder 实现。\n\n比如 `Kafka` 的实现 `KafkaMessageChannelBinder`，`RabbitMQ` 的实现 `RabbitMessageChannelBinder` 以及 `RocketMQ` 的实现 `RocketMQMessageChannelBinder`。\n\n* Binding: 包括 Input Binding 和 Output Binding。\n\nBinding 在消息中间件与应用程序提供的 Provider 和 Consumer 之间提供了一个桥梁，实现了开发者只需使用应用程序的 Provider 或 Consumer 生产或消费数据即可，屏蔽了开发者与底层消息中间件的接触。\n\n下图是 Spring Cloud Stream 的架构设计。\n\n![](https://docs.spring.io/spring-cloud-stream/docs/current/reference/html/images/SCSt-with-binder.png)\n\n\n\n## 准备工作\n\n### 下载并启动 RocketMQ\n\n**在接入 RocketMQ Binder 之前，首先需要启动 RocketMQ 的 Name Server 和 Broker。**\n\n1. 下载[RocketMQ最新的二进制文件](https://www.apache.org/dyn/closer.cgi?path=rocketmq/4.3.2/rocketmq-all-4.3.2-bin-release.zip)，并解压\n\n2. 启动 Name Server\n\n```bash\nsh bin/mqnamesrv\n```\n\n3. 启动 Broker\n\n```bash\nsh bin/mqbroker -n localhost:9876\n```\n\n### 引入依赖\n\n修改 `pom.xml` 文件，引入 RocketMQ Stream Starter。\n\n```xml\n<dependency>\n    <groupId>com.alibaba.cloud</groupId>\n    <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n</dependency>\n```\n\n## 简单示例\n\n### 创建Topic\n\n```sh\nsh bin/mqadmin updateTopic -n localhost:9876 -c DefaultCluster -t test-topic\n```\n\n### 示例代码\n\n配置 Input 和 Output 的 Binding 信息并配合 `@EnableBinding` 注解使其生效\n\n```java\n@SpringBootApplication\n@EnableBinding({ Source.class, Sink.class })\npublic class RocketMQApplication {\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(RocketMQApplication.class, args);\n\t}\n}\n```\n\n配置 Binding 信息：\n```properties\n# 配置rocketmq的nameserver地址\nspring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876\n# 定义name为output的binding\nspring.cloud.stream.bindings.output.destination=test-topic\nspring.cloud.stream.bindings.output.content-type=application/json\n# 定义name为input的binding\nspring.cloud.stream.bindings.input.destination=test-topic\nspring.cloud.stream.bindings.input.content-type=application/json\nspring.cloud.stream.bindings.input.group=test-group\n```\n\n### 应用启动\n\n1. 增加配置，在应用的 /src/main/resources/application.properties 中添加基本配置信息\n\t\n```properties\nspring.application.name=rocketmq-example\nserver.port=28081\n```\n\n2. 启动应用，支持 IDE 直接启动和编译打包后启动。\n\n\t1. IDE 直接启动：找到主类 `RocketMQApplication`，执行 main 方法启动应用。\n\t2. 打包编译后启动：首先执行 `mvn clean package` 将工程编译打包，然后执行 `java -jar rocketmq-example.jar` 启动应用。\n\n\n### 消息处理\n\n使用 name 为 output 对应的 binding 发送消息到 test-topic 这个 topic。\n\n使用2个 input binding 订阅数据。\n\n* input1: 订阅 topic 为 test-topic 的消息，顺序消费所有消息(顺序消费的前提是所有消息都在一个 MessageQueue 中)\n\n* input2: 订阅 topic 为 test-topic 的消息，异步消费 tags 为 tagStr 的消息，Consumer 端线程池个数为20\n\n配置信息如下：\n\n```properties\nspring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876\n\nspring.cloud.stream.bindings.output.destination=test-topic\nspring.cloud.stream.bindings.output.content-type=application/json\n\nspring.cloud.stream.bindings.input1.destination=test-topic\nspring.cloud.stream.bindings.input1.content-type=text/plain\nspring.cloud.stream.bindings.input1.group=test-group1\nspring.cloud.stream.rocketmq.bindings.input1.consumer.orderly=true\n\nspring.cloud.stream.bindings.input2.destination=test-topic\nspring.cloud.stream.bindings.input2.content-type=text/plain\nspring.cloud.stream.bindings.input2.group=test-group2\nspring.cloud.stream.rocketmq.bindings.input2.consumer.orderly=false\nspring.cloud.stream.rocketmq.bindings.input2.consumer.tags=tagStr\nspring.cloud.stream.bindings.input2.consumer.concurrency=20\n\n```\n\n#### 消息发送\n\n使用 MessageChannel 进行消息发送：\n\n```java\npublic class ProducerRunner implements CommandLineRunner {\n    @Autowired\n    private MessageChannel output; // 获取name为output的binding\n    @Override\n    public void run(String... args) throws Exception {\n        Map<String, Object> headers = new HashMap<>();\n        headers.put(MessageConst.PROPERTY_TAGS, \"tagStr\");\n        Message message = MessageBuilder.createMessage(msg, new MessageHeaders(headers));\n        output.send(message);\n    }\n}\n```\n\n或者使用 RocketMQ 原生的 API 进行消息发送:\n\n```java\npublic class RocketMQProducer {\n    DefaultMQProducer producer = new DefaultMQProducer(\"producer_group\");\n    producer.setNamesrvAddr(\"127.0.0.1:9876\");\n    producer.start();\n    \n    Message msg = new Message(\"test-topic\", \"tagStr\", \"message from rocketmq producer\".getBytes());\n    producer.send(msg);\n}\n```\n\n#### 消息接收\n\n使用 `@StreamListener` 注解接收消息：\n\n```java\n@Service\npublic class ReceiveService {\n\n\t@StreamListener(\"input1\")\n\tpublic void receiveInput1(String receiveMsg) {\n\t\tSystem.out.println(\"input1 receive: \" + receiveMsg);\n\t}\n\n\t@StreamListener(\"input2\")\n\tpublic void receiveInput2(String receiveMsg) {\n\t\tSystem.out.println(\"input2 receive: \" + receiveMsg);\n\t}\n\n}\n```\n\n## 广播消费示例\n\n​\t广播会发送消息给所有消费者。如果你想同一消费组下所有消费者接收到同一个topic下的消息，广播消费非常适合此场景。\n\n### 创建Topic\n\n```sh\nsh bin/mqadmin updateTopic -n localhost:9876 -c DefaultCluster -t broadcast\n```\n\n### 生产者\n\n**application.yml**\n\n```yaml\nserver:\n  port: 28085\nspring:\n  application:\n    name: rocketmq-broadcast-producer-example\n  cloud:\n    stream:\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          producer-out-0:\n            producer:\n              group: output_1\n      bindings:\n        producer-out-0:\n          destination: broadcast\nlogging:\n  level:\n    org.springframework.context.support: debug\n```\n\n**code**\n\n使用`ApplicationRunner`和`StreamBridge`发送消息。\n\n```java\n@SpringBootApplication\npublic class RocketMQBroadcastProducerApplication {\n   private static final Logger log = LoggerFactory\n         .getLogger(RocketMQBroadcastProducerApplication.class);\n   @Autowired\n   private StreamBridge streamBridge;\n   public static void main(String[] args) {\n      SpringApplication.run(RocketMQBroadcastProducerApplication.class, args);\n   }\n\n   @Bean\n   public ApplicationRunner producer() {\n      return args -> {\n         for (int i = 0; i < 100; i++) {\n            String key = \"KEY\" + i;\n            Map<String, Object> headers = new HashMap<>();\n            headers.put(MessageConst.PROPERTY_KEYS, key);\n            headers.put(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID, i);\n            Message<SimpleMsg> msg = new GenericMessage<SimpleMsg>(new SimpleMsg(\"Hello RocketMQ \" + i), headers);\n            streamBridge.send(\"producer-out-0\", msg);\n         }\n      };\n   }\n}\n```\n\n### 消费者\n\n启动两个消费者实例。\n\n#### 消费者1\n\n**application.yml**\n\n```yaml\nserver:\n  port: 28084\nspring:\n  application:\n    name: rocketmq-broadcast-consumer1-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          consumer-in-0:\n            consumer:\n              messageModel: BROADCASTING\n      bindings:\n        consumer-in-0:\n          destination: broadcast\n          group: broadcast-consumer\nlogging:\n  level:\n    org.springframework.context.support: debug\n```\n\n**code**\n\n```java\n@SpringBootApplication\npublic class RocketMQBroadcastConsumer1Application {\n   private static final Logger log = LoggerFactory\n         .getLogger(RocketMQBroadcastConsumer1Application.class);\n\n   public static void main(String[] args) {\n      SpringApplication.run(RocketMQBroadcastConsumer1Application.class, args);\n   }\n\n   @Bean\n   public Consumer<Message<SimpleMsg>> consumer() {\n      return msg -> {\n         log.info(Thread.currentThread().getName() + \" Consumer1 Receive New Messages: \" + msg.getPayload().getMsg());\n      };\n   }\n}\n```\n\n#### 消费者2\n\n**application.yml**\n\n```yaml\nserver:\n  port: 28083\nspring:\n  application:\n    name: rocketmq-broadcast-consumer2-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          consumer-in-0:\n            consumer:\n              messageModel: BROADCASTING\n      bindings:\n        consumer-in-0:\n          destination: broadcast\n          group: broadcast-consumer\nlogging:\n  level:\n    org.springframework.context.support: debug\n```\n\n**code**\n\n```java\n@SpringBootApplication\npublic class RocketMQBroadcastConsumer2Application {\n   private static final Logger log = LoggerFactory\n         .getLogger(RocketMQBroadcastConsumer2Application.class);\n\n   public static void main(String[] args) {\n      SpringApplication.run(RocketMQBroadcastConsumer2Application.class, args);\n   }\n\n   @Bean\n   public Consumer<Message<SimpleMsg>> consumer() {\n      return msg -> {\n         log.info(Thread.currentThread().getName() + \" Consumer2 Receive New Messages: \" + msg.getPayload().getMsg());\n      };\n   }\n}\n```\n\n## 顺序消费示例\n\n顺序消息（FIFO消息）是消息队列RocketMQ版提供的一种严格按照顺序来发布和消费的消息类型。\n\n顺序消息分为两类：\n\n- 全局顺序：对于指定的一个Topic，所有消息按照严格的先入先出FIFO（First In First Out）的顺序进行发布和消费。分区顺序：对于指定的一个Topic，所有消息根据Sharding Key进行区块分区。同一个分区内的消息按照严格的FIFO顺序进行发布和消费。Sharding Key是顺序消息中用来区分不同分区的关键字段，和普通消息的Key是完全不同的概念。\n\n### 创建Topic\n\n```sh\nsh bin/mqadmin updateTopic -n localhost:9876 -c DefaultCluster -t orderly\n```\n\n### 示例代码\n\n**application.yml**\n\n```yaml\nserver:\n  port: 28082\nspring:\n  application:\n    name: rocketmq-orderly-consume-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          producer-out-0:\n            producer:\n              group: output_1\n              # 定义messageSelector\n              messageQueueSelector: orderlyMessageQueueSelector\n          consumer-in-0:\n            consumer:\n              # tag: {@code tag1||tag2||tag3 }; sql: {@code 'color'='blue' AND 'price'>100 } .\n              subscription: 'TagA || TagC || TagD'\n              push:\n                orderly: true\n      bindings:\n        producer-out-0:\n          destination: orderly\n        consumer-in-0:\n          destination: orderly\n          group: orderly-consumer\n\nlogging:\n  level:\n    org.springframework.context.support: debug\n```\n\n**MessageQueueSelector**\n\n选择适合自己的分区选择算法，保证同一个参数得到的结果相同。\n\n```java\n@Component\npublic class OrderlyMessageQueueSelector implements MessageQueueSelector {\n   private static final Logger log = LoggerFactory\n         .getLogger(OrderlyMessageQueueSelector.class);\n   @Override\n   public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {\n      Integer id = (Integer) ((MessageHeaders) arg).get(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID);\n      String tag = (String) ((MessageHeaders) arg).get(MessageConst.PROPERTY_TAGS);\n      int index = id % RocketMQOrderlyConsumeApplication.tags.length % mqs.size();\n      return mqs.get(index);\n   }\n}\n```\n\n**生产者&消费者**\n\n```java\n@SpringBootApplication\npublic class RocketMQOrderlyConsumeApplication {\n   private static final Logger log = LoggerFactory\n         .getLogger(RocketMQOrderlyConsumeApplication.class);\n\n   @Autowired\n   private StreamBridge streamBridge;\n\n   /***\n    * tag array.\n    */\n   public static final String[] tags = new String[] {\"TagA\", \"TagB\", \"TagC\", \"TagD\", \"TagE\"};\n\n   public static void main(String[] args) {\n      SpringApplication.run(RocketMQOrderlyConsumeApplication.class, args);\n   }\n\n   @Bean\n   public ApplicationRunner producer() {\n      return args -> {\n         for (int i = 0; i < 100; i++) {\n            String key = \"KEY\" + i;\n            Map<String, Object> headers = new HashMap<>();\n            headers.put(MessageConst.PROPERTY_KEYS, key);\n            headers.put(MessageConst.PROPERTY_TAGS, tags[i % tags.length]);\n            headers.put(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID, i);\n            Message<SimpleMsg> msg = new GenericMessage(new SimpleMsg(\"Hello RocketMQ \" + i), headers);\n            streamBridge.send(\"producer-out-0\", msg);\n         }\n      };\n   }\n\n   @Bean\n   public Consumer<Message<SimpleMsg>> consumer() {\n      return msg -> {\n         String tagHeaderKey = RocketMQMessageConverterSupport.toRocketHeaderKey(\n               MessageConst.PROPERTY_TAGS).toString();\n         log.info(Thread.currentThread().getName() + \" Receive New Messages: \" + msg.getPayload().getMsg() + \" TAG:\" +\n               msg.getHeaders().get(tagHeaderKey).toString());\n         try {\n            Thread.sleep(100);\n         }\n         catch (InterruptedException ignored) {\n         }\n      };\n   }\n\n}\n```\n\n## 延时消息示例\n\n- 延时消息：Producer将消息发送到消息队列RocketMQ服务端，但并不期望立马投递这条消息，而是延迟一定时间后才投递到Consumer进行消费，该消息即延时消息。\n\n### 创建Topic\n\n```sh\nsh bin/mqadmin updateTopic -n localhost:9876 -c DefaultCluster -t delay\n```\n\n### 示例代码\n\n**application.yml**\n\n```yaml\nserver:\n  port: 28086\nspring:\n  application:\n    name: rocketmq-delay-consume-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          producer-out-0:\n            producer:\n              group: output_1\n      bindings:\n        producer-out-0:\n          destination: delay\n        consumer-in-0:\n          destination: delay\n          group: delay-group\nlogging:\n  level:\n    org.springframework.context.support: debug\n```\n\n**code**\n\n```java\n@SpringBootApplication\npublic class RocketMQDelayConsumeApplication {\n   private static final Logger log = LoggerFactory\n         .getLogger(RocketMQDelayConsumeApplication.class);\n   @Autowired\n   private StreamBridge streamBridge;\n\n   public static void main(String[] args) {\n      SpringApplication.run(RocketMQDelayConsumeApplication.class, args);\n   }\n\n   @Bean\n   public ApplicationRunner producerDelay() {\n      return args -> {\n         for (int i = 0; i < 100; i++) {\n            String key = \"KEY\" + i;\n            Map<String, Object> headers = new HashMap<>();\n            headers.put(MessageConst.PROPERTY_KEYS, key);\n            headers.put(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID, i);\n   \t\t\t// 设置延时等级1~10\n            headers.put(MessageConst.PROPERTY_DELAY_TIME_LEVEL, 2);\n            Message<SimpleMsg> msg = new GenericMessage(new SimpleMsg(\"Delay RocketMQ \" + i), headers);\n            streamBridge.send(\"producer-out-0\", msg);\n         }\n      };\n   }\n\n   @Bean\n   public Consumer<Message<SimpleMsg>> consumer() {\n      return msg -> {\n         log.info(Thread.currentThread().getName() + \" Consumer Receive New Messages: \" + msg.getPayload().getMsg());\n      };\n   }\n}\n```\n\n## 过滤消息示例\n\n### 创建Topic\n\n```sh\nsh bin/mqadmin updateTopic -n localhost:9876 -c DefaultCluster -t sql\n```\n\n### 示例代码\n\n**application.yml**\n\n支持tag过滤或者sql过滤，设置`spring.cloud.stream.rocketmq.bindings.<channelName>.consumer.subscription`即可。\n\ntag示例: `tag:red || blue`\n\nsql示例: `sql:(color in ('red1', 'red2', 'red4') and price>3)`\n\n更多请参考: [Filter](https://rocketmq.apache.org/docs/filter-by-sql92-example/)\n\n```yaml\nserver:\n  port: 28087\nspring:\n  application:\n    name: rocketmq-sql-consume-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          producer-out-0:\n            producer:\n              group: output_1\n          consumer-in-0:\n            consumer:\n              # tag: {@code tag1||tag2||tag3 }; sql: {@code 'color'='blue' AND 'price'>100 } .\n              subscription: sql:(color in ('red1', 'red2', 'red4') and price>3)\n      bindings:\n        producer-out-0:\n          destination: sql\n        consumer-in-0:\n          destination: sql\n          group: sql-group\nlogging:\n  level:\n    org.springframework.context.support: debug\n```\n\n**code**\n\n```java\n@SpringBootApplication\npublic class RocketMQSqlConsumeApplication {\n   private static final Logger log = LoggerFactory\n         .getLogger(RocketMQSqlConsumeApplication.class);\n   @Autowired\n   private StreamBridge streamBridge;\n   public static void main(String[] args) {\n      SpringApplication.run(RocketMQSqlConsumeApplication.class, args);\n   }\n\n   /**\n    * color array.\n    */\n   public static final String[] color = new String[] {\"red1\", \"red2\", \"red3\", \"red4\", \"red5\"};\n\n   /**\n    * price array.\n    */\n   public static final Integer[] price = new Integer[] {1, 2, 3, 4, 5};\n\n   @Bean\n   public ApplicationRunner producer() {\n      return args -> {\n         for (int i = 0; i < 100; i++) {\n            String key = \"KEY\" + i;\n            Map<String, Object> headers = new HashMap<>();\n            headers.put(MessageConst.PROPERTY_KEYS, key);\n            headers.put(\"color\", color[i % color.length]);\n            headers.put(\"price\", price[i % price.length]);\n            headers.put(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID, i);\n            Message<SimpleMsg> msg = new GenericMessage(new SimpleMsg(\"Hello RocketMQ \" + i), headers);\n            streamBridge.send(\"producer-out-0\", msg);\n         }\n      };\n   }\n\n   @Bean\n   public Consumer<Message<SimpleMsg>> consumer() {\n      return msg -> {\n         String colorHeaderKey = \"color\";\n         String priceHeaderKey = \"price\";\n         log.info(Thread.currentThread().getName() + \" Receive New Messages: \" + msg.getPayload().getMsg() + \" COLOR:\" +\n               msg.getHeaders().get(colorHeaderKey).toString() + \" \" +\n               \"PRICE: \" + msg.getHeaders().get(priceHeaderKey).toString());\n      };\n   }\n}\n```\n\n#### 常见问题\n\n- MQClientException: The broker does not support consumer to filter message by SQL92  \n1. 修改 RocketMQ 服务端配置文件。\n在 `conf/2m-2s-async/broker-a.properties` 配置文件末尾添加 `enablePropertyFilter=true`  \n2. 重启 mqbroker 并指定配置文件。\n`mqbroker` 启动时指定配置文件：`conf/2m-2s-async/broker-a.properties`，例如：\n```shell\nbin/mqbroker -n 127.0.0.1:9876 -c conf/2m-2s-async/broker-a.properties autoCreateTopicEnable=true  \n```\n\n## 事务消息示例\n\n### 什么是事务消息?\n\n参考[Transaction Example](https://rocketmq.apache.org/docs/transaction-example/).\n\n> 可以被认为是一个两阶段的提交消息实现，以确保分布式系统的最终一致性。 事务性消息确保本地事务的执行和消息的发送可以原子地执行。\n\n### Application\n\n> 1、 事务装填\n>\n> 事务消息有三个状态:\n> (1) TransactionStatus.CommitTransaction: 提交事务，意味着消费者可以消费事务\n> (2) TransactionStatus.RollbackTransaction: 回滚事务，消息将被删除，并且不允许被消费。\n> (3) TransactionStatus.Unknown: 中间状态，意味着MQ需要回查最终状态。\n\n### 创建Topic\n\n```sh\nsh bin/mqadmin updateTopic -n localhost:9876 -c DefaultCluster -t tx\n```\n\n### 示例代码\n\n**application.yml**\n\n```yaml\nserver:\n  port: 28088\nspring:\n  application:\n    name: rocketmq-tx-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          producer-out-0:\n            producer:\n              group: output_1\n              transactionListener: myTransactionListener\n              producerType: Trans\n      bindings:\n        producer-out-0:\n          destination: tx\n        consumer-in-0:\n          destination: tx\n          group: tx-group\nlogging:\n  level:\n    org.springframework.context.support: debug\n```\n\n**TransactionListenerImpl**\n\n执行本地事务。\n\n```java\n@Component(\"myTransactionListener\")\npublic class TransactionListenerImpl implements TransactionListener {\n\n\t@Override\n\tpublic LocalTransactionState executeLocalTransaction(Message msg, Object arg) {\n\t\tObject num = msg.getProperty(\"test\");\n\n\t\tif (\"1\".equals(num)) {\n\t\t\tSystem.out.println(\"executer: \" + new String(msg.getBody()) + \" unknown\");\n\t\t\treturn LocalTransactionState.UNKNOW;\n\t\t}\n\t\telse if (\"2\".equals(num)) {\n\t\t\tSystem.out.println(\"executer: \" + new String(msg.getBody()) + \" rollback\");\n\t\t\treturn LocalTransactionState.ROLLBACK_MESSAGE;\n\t\t}\n\t\tSystem.out.println(\"executer: \" + new String(msg.getBody()) + \" commit\");\n\t\treturn LocalTransactionState.COMMIT_MESSAGE;\n\t}\n\n\t@Override\n\tpublic LocalTransactionState checkLocalTransaction(MessageExt msg) {\n\t\tSystem.out.println(\"check: \" + new String(msg.getBody()));\n\t\treturn LocalTransactionState.COMMIT_MESSAGE;\n\t}\n\n}\n```\n\n**producer and consumer**\n\n```java\n@SpringBootApplication\npublic class RocketMQTxApplication {\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(RocketMQTxApplication.class);\n\t@Autowired\n\tprivate StreamBridge streamBridge;\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(RocketMQTxApplication.class, args);\n\t}\n\n\n\t@Bean\n\tpublic ApplicationRunner producer() {\n\t\treturn args -> {\n\t\t\tfor (int i = 1; i <= 4; i++) {\n\t\t\t\tMessageBuilder builder = MessageBuilder.withPayload(new SimpleMsg(\"Hello Tx msg \" + i));\n\t\t\t\tbuilder.setHeader(\"test\", String.valueOf(i))\n\t\t\t\t\t\t.setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON);\n\t\t\t\tbuilder.setHeader(RocketMQConst.USER_TRANSACTIONAL_ARGS, \"binder\");\n\t\t\t\tMessage<SimpleMsg> msg = builder.build();\n\t\t\t\tstreamBridge.send(\"producer-out-0\", msg);\n\t\t\t\tSystem.out.println(\"send Msg:\" + msg.toString());\n\t\t\t}\n\t\t};\n\t}\n\n\t@Bean\n\tpublic Consumer<Message<SimpleMsg>> consumer() {\n\t\treturn msg -> {\n\t\t\tObject arg = msg.getHeaders();\n\t\t\tlog.info(Thread.currentThread().getName() + \" Receive New Messages: \" + msg.getPayload().getMsg() + \" ARG:\"\n\t\t\t\t+ arg.toString());\n\t\t};\n\t}\n}\n```\n\n## Endpoint 信息查看\n\nSpring Boot 应用支持通过 Endpoint 来暴露相关信息，RocketMQ Stream Starter 也支持这一点。\n\n在使用之前需要在 Maven 中添加 `spring-boot-starter-actuator`依赖，并在配置中允许 Endpoints 的访问。\n* Spring Boot 1.x 中添加配置 `management.security.enabled=false`\n* Spring Boot 2.x 中添加配置 `management.endpoints.web.exposure.include=*`\n\nSpring Boot 1.x 可以通过访问 http://127.0.0.1:18083/rocketmq_binder 来查看 RocketMQ Binder Endpoint 的信息。Spring Boot 2.x 可以通过访问 http://127.0.0.1:28081/actuator/rocketmq-binder 来访问。\n\n这里会统计消息最后一次发送的数据，消息发送成功或失败的次数，消息消费成功或失败的次数等数据。\n\n```json\n{\n\t\"runtime\": {\n\t\t\"lastSend.timestamp\": 1542786623915\n\t},\n\t\"metrics\": {\n\t\t\"scs-rocketmq.consumer.test-topic.totalConsumed\": {\n\t\t\t\"count\": 11\n\t\t},\n\t\t\"scs-rocketmq.consumer.test-topic.totalConsumedFailures\": {\n\t\t\t\"count\": 0\n\t\t},\n\t\t\"scs-rocketmq.producer.test-topic.totalSentFailures\": {\n\t\t\t\"count\": 0\n\t\t},\n\t\t\"scs-rocketmq.consumer.test-topic.consumedPerSecond\": {\n\t\t\t\"count\": 11,\n\t\t\t\"fifteenMinuteRate\": 0.012163847780107841,\n\t\t\t\"fiveMinuteRate\": 0.03614605351360527,\n\t\t\t\"meanRate\": 0.3493213353657594,\n\t\t\t\"oneMinuteRate\": 0.17099243039490175\n\t\t},\n\t\t\"scs-rocketmq.producer.test-topic.totalSent\": {\n\t\t\t\"count\": 5\n\t\t},\n\t\t\"scs-rocketmq.producer.test-topic.sentPerSecond\": {\n\t\t\t\"count\": 5,\n\t\t\t\"fifteenMinuteRate\": 0.005540151995103271,\n\t\t\t\"fiveMinuteRate\": 0.01652854617838251,\n\t\t\t\"meanRate\": 0.10697493212602836,\n\t\t\t\"oneMinuteRate\": 0.07995558537067671\n\t\t},\n\t\t\"scs-rocketmq.producer.test-topic.sentFailuresPerSecond\": {\n\t\t\t\"count\": 0,\n\t\t\t\"fifteenMinuteRate\": 0.0,\n\t\t\t\"fiveMinuteRate\": 0.0,\n\t\t\t\"meanRate\": 0.0,\n\t\t\t\"oneMinuteRate\": 0.0\n\t\t},\n\t\t\"scs-rocketmq.consumer.test-topic.consumedFailuresPerSecond\": {\n\t\t\t\"count\": 0,\n\t\t\t\"fifteenMinuteRate\": 0.0,\n\t\t\t\"fiveMinuteRate\": 0.0,\n\t\t\t\"meanRate\": 0.0,\n\t\t\t\"oneMinuteRate\": 0.0\n\t\t}\n\t}\n}\n```\n\n注意：要想查看统计数据需要在pom里加上 [metrics-core依赖](https://mvnrepository.com/artifact/io.dropwizard.metrics/metrics-core)。如若不加，endpoint 将会显示 warning 信息而不会显示统计信息：\n\n```json\n{\n    \"warning\": \"please add metrics-core dependency, we use it for metrics\"\n}\n```\n\n## More\n\nRocketMQ 是一款功能强大的分布式消息系统，广泛应用于多个领域，包括异步通信解耦、企业解决方案、金融支付、电信、电子商务、快递物流、广告营销、社交、即时通信、移动应用、手游、视频、物联网、车联网等。\n\n此 Demo 仅演示了 RocketMQ 与 Spring Cloud Stream 结合后的使用，更多 RocketMQ 相关的信息，请参考 [RocketMQ 项目](https://github.com/apache/rocketmq)。\n\n如果您对 spring cloud starter stream rocketmq 有任何建议或想法，欢迎在 issue 中或者通过其他社区渠道向我们提出。\n\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/readme.md",
    "content": "# RocketMQ Example\n\n## Project Instruction\n\nThis example illustrates how to use RocketMQ Binder implement pub/sub messages for Spring Cloud applications.\n\n[RocketMQ](https://rocketmq.apache.org/) is a distributed messaging and streaming platform with low latency, high performance and reliability, trillion-level capacity and flexible scalability.\n\nBefore we start the demo, let's look at Spring Cloud Stream.\n\nSpring Cloud Stream is a framework for building message-driven microservice applications. Spring Cloud Stream builds upon Spring Boot to create standalone, production-grade Spring applications and uses Spring Integration to provide connectivity to message brokers. It provides opinionated configuration of middleware from several vendors, introducing the concepts of persistent publish-subscribe semantics, consumer groups, and partitions.\n\nThere are two concepts in Spring Cloud Stream: Binder 和 Binding.\n\n* Binder: A strategy interface used to bind an app interface to a logical name.\n\nBinder Implementations includes `KafkaMessageChannelBinder` of kafka, `RabbitMessageChannelBinder` of RabbitMQ and `RocketMQMessageChannelBinder` of `RocketMQ`.  \n\n* Binding: Including Input Binding and Output Binding.\n\nBinding is Bridge between the external messaging systems and application provided Producers and Consumers of messages.\n\nThis is a overview of Spring Cloud Stream.\n\n![](https://docs.spring.io/spring-cloud-stream/docs/current/reference/html/images/SCSt-with-binder.png)\n\n## Preparation\n\n### Download and Startup RocketMQ\n\nYou should startup Name Server and Broker before using RocketMQ Binder.\n\n1. Download [RocketMQ](https://archive.apache.org/dist/rocketmq/4.3.2/rocketmq-all-4.3.2-bin-release.zip) and unzip it.\n\n2. Startup Name Server\n\n```bash\nsh bin/mqnamesrv\n```\n\n3. Startup Broker\n\n```bash\nsh bin/mqbroker -n localhost:9876\n```\n\n### Declare dependency\n\nAdd dependency spring-cloud-starter-stream-rocketmq to the `pom.xml` file in your Spring Cloud project.\n\n```xml\n<dependency>\n    <groupId>com.alibaba.cloud</groupId>\n    <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n</dependency>\n```\n\n## Simple example\n\n### Create topic\n\n```sh\nsh bin/mqadmin updateTopic -n localhost:9876 -c DefaultCluster -t test-topic\n```\n\n### Integration with RocketMQ Binder\n\nConfigure Input and Output Binding and cooperate with `@EnableBinding` annotation\n\n```java\n@SpringBootApplication\n@EnableBinding({ Source.class, Sink.class })\npublic class RocketMQApplication {\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(RocketMQApplication.class, args);\n\t}\n}\n```\n\nConfigure Binding:\n```properties\n# configure the nameserver of rocketmq\nspring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876\n# configure the output binding named output\nspring.cloud.stream.bindings.output.destination=test-topic\nspring.cloud.stream.bindings.output.content-type=application/json\n# configure the input binding named input\nspring.cloud.stream.bindings.input.destination=test-topic\nspring.cloud.stream.bindings.input.content-type=application/json\nspring.cloud.stream.bindings.input.group=test-group\n\n```\n\n### Start Application\n\n1. Add necessary configurations to file `/src/main/resources/application.properties`.\n\t\n```properties\nspring.application.name=rocketmq-example\nserver.port=28081\n```\n\n2. Start the application in IDE or by building a fatjar.\n\n\t1. Start in IDE: Find main class  `RocketMQApplication`, and execute the main method.\n    2. Build a fatjar: Execute command `mvn clean package` to build a fatjar, and run command `java -jar rocketmq-example.jar` to start the application.\n\n\n### Message Handle\n\nUsing the binding named output and sent messages to `test-topic` topic.\n\nAnd using two input bindings to subscribe messages.\n\n* input1: subscribe the message of `test-topic` topic and consume ordered messages(all messages should in the same MessageQueue if you want to consuming ordered messages).\n\n* input2: subscribe the message of `test-topic` topic and consume concurrent messages which tags is `tagStr`, the thread number in pool is 20 in Consumer side.\n\nsee the configuration below:\n\n```properties\nspring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876\n\nspring.cloud.stream.bindings.output.destination=test-topic\nspring.cloud.stream.bindings.output.content-type=application/json\n\nspring.cloud.stream.bindings.input1.destination=test-topic\nspring.cloud.stream.bindings.input1.content-type=text/plain\nspring.cloud.stream.bindings.input1.group=test-group1\nspring.cloud.stream.rocketmq.bindings.input1.consumer.orderly=true\n\nspring.cloud.stream.bindings.input2.destination=test-topic\nspring.cloud.stream.bindings.input2.content-type=text/plain\nspring.cloud.stream.bindings.input2.group=test-group2\nspring.cloud.stream.rocketmq.bindings.input2.consumer.orderly=false\nspring.cloud.stream.rocketmq.bindings.input2.consumer.tags=tagStr\nspring.cloud.stream.bindings.input2.consumer.concurrency=20\n\n```\n\n#### Pub Messages\n\nUsing MessageChannel to send messages:\n\n```java\npublic class ProducerRunner implements CommandLineRunner {\n    @Autowired\n    private MessageChannel output;\n    @Override\n    public void run(String... args) throws Exception {\n        Map<String, Object> headers = new HashMap<>();\n        headers.put(MessageConst.PROPERTY_TAGS, \"tagStr\");\n        Message message = MessageBuilder.createMessage(msg, new MessageHeaders(headers));\n        output.send(message);\n    }\n}\n```\n\nOr you can using the native API of RocketMQ to send messages:\n\n```java\npublic class RocketMQProducer {\n    DefaultMQProducer producer = new DefaultMQProducer(\"producer_group\");\n    producer.setNamesrvAddr(\"127.0.0.1:9876\");\n    producer.start();\n    \n    Message msg = new Message(\"test-topic\", \"tagStr\", \"message from rocketmq producer\".getBytes());\n    producer.send(msg);\n}\n```\n\n#### Sub Messages\n\nUsing `@StreamListener` to receive messages:\n\n```java\n@Service\npublic class ReceiveService {\n\n\t@StreamListener(\"input1\")\n\tpublic void receiveInput1(String receiveMsg) {\n\t\tSystem.out.println(\"input1 receive: \" + receiveMsg);\n\t}\n\n\t@StreamListener(\"input2\")\n\tpublic void receiveInput2(String receiveMsg) {\n\t\tSystem.out.println(\"input2 receive: \" + receiveMsg);\n\t}\n\n}\n```\n\n## Broadcasting exmaple\n\n### Create topic\n\n```sh\nsh bin/mqadmin updateTopic -n localhost:9876 -c DefaultCluster -t broadcast\n```\n\n### Producer\n\n**application.yml**\n\n```yaml\nserver:\n  port: 28085\nspring:\n  application:\n    name: rocketmq-broadcast-producer-example\n  cloud:\n    stream:\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          producer-out-0:\n            producer:\n              group: output_1\n      bindings:\n        producer-out-0:\n          destination: broadcast\nlogging:\n  level:\n    org.springframework.context.support: debug\n```\n\n**code**\n\nUse `ApplicationRunner` and `StreamBridge` to send messages.\n\n```java\n@SpringBootApplication\npublic class RocketMQBroadcastProducerApplication {\n   private static final Logger log = LoggerFactory\n         .getLogger(RocketMQBroadcastProducerApplication.class);\n   @Autowired\n   private StreamBridge streamBridge;\n   public static void main(String[] args) {\n      SpringApplication.run(RocketMQBroadcastProducerApplication.class, args);\n   }\n\n   @Bean\n   public ApplicationRunner producer() {\n      return args -> {\n         for (int i = 0; i < 100; i++) {\n            String key = \"KEY\" + i;\n            Map<String, Object> headers = new HashMap<>();\n            headers.put(MessageConst.PROPERTY_KEYS, key);\n            headers.put(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID, i);\n            Message<SimpleMsg> msg = new GenericMessage<SimpleMsg>(new SimpleMsg(\"Hello RocketMQ \" + i), headers);\n            streamBridge.send(\"producer-out-0\", msg);\n         }\n      };\n   }\n}\n```\n\n### Consumer\n\nStartup two consumers.\n\n#### Consumer1\n\n**application.yml**\n\n```yaml\nserver:\n  port: 28084\nspring:\n  application:\n    name: rocketmq-broadcast-consumer1-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          consumer-in-0:\n            consumer:\n              messageModel: BROADCASTING\n      bindings:\n        consumer-in-0:\n          destination: broadcast\n          group: broadcast-consumer\nlogging:\n  level:\n    org.springframework.context.support: debug\n```\n\n**code**\n\n```java\n@SpringBootApplication\npublic class RocketMQBroadcastConsumer1Application {\n   private static final Logger log = LoggerFactory\n         .getLogger(RocketMQBroadcastConsumer1Application.class);\n\n   public static void main(String[] args) {\n      SpringApplication.run(RocketMQBroadcastConsumer1Application.class, args);\n   }\n\n   @Bean\n   public Consumer<Message<SimpleMsg>> consumer() {\n      return msg -> {\n         log.info(Thread.currentThread().getName() + \" Consumer1 Receive New Messages: \" + msg.getPayload().getMsg());\n      };\n   }\n}\n```\n\n#### Consumer2\n\n**application.yml**\n\n```yaml\nserver:\n  port: 28083\nspring:\n  application:\n    name: rocketmq-broadcast-consumer2-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          consumer-in-0:\n            consumer:\n              messageModel: BROADCASTING\n      bindings:\n        consumer-in-0:\n          destination: broadcast\n          group: broadcast-consumer\nlogging:\n  level:\n    org.springframework.context.support: debug\n```\n\n**code**\n\n```java\n@SpringBootApplication\npublic class RocketMQBroadcastConsumer2Application {\n   private static final Logger log = LoggerFactory\n         .getLogger(RocketMQBroadcastConsumer2Application.class);\n\n   public static void main(String[] args) {\n      SpringApplication.run(RocketMQBroadcastConsumer2Application.class, args);\n   }\n\n   @Bean\n   public Consumer<Message<SimpleMsg>> consumer() {\n      return msg -> {\n         log.info(Thread.currentThread().getName() + \" Consumer2 Receive New Messages: \" + msg.getPayload().getMsg());\n      };\n   }\n}\n```\n\n## Order example\n\n​\tRocketMQ provides ordered messages using FIFO order.\n\n​\tThere are two types of ordered messages.\n\n* Global: For a specified topic, all messages are published and consumed in strict FIFO (First In First Out) order.\n* Partition: For a specified topic, all messages are partitioned according to the `Sharding Key`. Messages within the same partition are published and consumed in strict FIFO order. `Sharding Key` is a key field used to distinguish different partitions in sequential messages, and it is a completely different concept from the Key of ordinary messages.\n\n### Create Topic\n\n```sh\nsh bin/mqadmin updateTopic -n localhost:9876 -c DefaultCluster -t orderly\n```\n\n### Example code\n\n**application.yml**\n\n```yaml\nserver:\n  port: 28082\nspring:\n  application:\n    name: rocketmq-orderly-consume-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          producer-out-0:\n            producer:\n              group: output_1\n              # 定义messageSelector\n              messageQueueSelector: orderlyMessageQueueSelector\n          consumer-in-0:\n            consumer:\n              # tag: {@code tag1||tag2||tag3 }; sql: {@code 'color'='blue' AND 'price'>100 } .\n              subscription: 'TagA || TagC || TagD'\n              push:\n                orderly: true\n      bindings:\n        producer-out-0:\n          destination: orderly\n        consumer-in-0:\n          destination: orderly\n          group: orderly-consumer\n\nlogging:\n  level:\n    org.springframework.context.support: debug\n```\n\n**MessageQueueSelector**\n\nChoose a partition selection algorithm for you, and ensure that the same parameters get the same results.\n\n```java\n@Component\npublic class OrderlyMessageQueueSelector implements MessageQueueSelector {\n   private static final Logger log = LoggerFactory\n         .getLogger(OrderlyMessageQueueSelector.class);\n   @Override\n   public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {\n      Integer id = (Integer) ((MessageHeaders) arg).get(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID);\n      String tag = (String) ((MessageHeaders) arg).get(MessageConst.PROPERTY_TAGS);\n      int index = id % RocketMQOrderlyConsumeApplication.tags.length % mqs.size();\n      return mqs.get(index);\n   }\n}\n```\n\n**Producer&Consumer**\n\n```java\n@SpringBootApplication\npublic class RocketMQOrderlyConsumeApplication {\n   private static final Logger log = LoggerFactory\n         .getLogger(RocketMQOrderlyConsumeApplication.class);\n\n   @Autowired\n   private StreamBridge streamBridge;\n\n   /***\n    * tag array.\n    */\n   public static final String[] tags = new String[] {\"TagA\", \"TagB\", \"TagC\", \"TagD\", \"TagE\"};\n\n   public static void main(String[] args) {\n      SpringApplication.run(RocketMQOrderlyConsumeApplication.class, args);\n   }\n\n   @Bean\n   public ApplicationRunner producer() {\n      return args -> {\n         for (int i = 0; i < 100; i++) {\n            String key = \"KEY\" + i;\n            Map<String, Object> headers = new HashMap<>();\n            headers.put(MessageConst.PROPERTY_KEYS, key);\n            headers.put(MessageConst.PROPERTY_TAGS, tags[i % tags.length]);\n            headers.put(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID, i);\n            Message<SimpleMsg> msg = new GenericMessage(new SimpleMsg(\"Hello RocketMQ \" + i), headers);\n            streamBridge.send(\"producer-out-0\", msg);\n         }\n      };\n   }\n\n   @Bean\n   public Consumer<Message<SimpleMsg>> consumer() {\n      return msg -> {\n         String tagHeaderKey = RocketMQMessageConverterSupport.toRocketHeaderKey(\n               MessageConst.PROPERTY_TAGS).toString();\n         log.info(Thread.currentThread().getName() + \" Receive New Messages: \" + msg.getPayload().getMsg() + \" TAG:\" +\n               msg.getHeaders().get(tagHeaderKey).toString());\n         try {\n            Thread.sleep(100);\n         }\n         catch (InterruptedException ignored) {\n         }\n      };\n   }\n\n}\n```\n\n## Schedule example\n\nScheduled messages differ from normal messages in that they won’t be delivered until a provided time later.\n\n### Create topic\n\n```sh\nsh bin/mqadmin updateTopic -n localhost:9876 -c DefaultCluster -t delay\n```\n\n### Example code\n\n**application.yml**\n\n```yaml\nserver:\n  port: 28086\nspring:\n  application:\n    name: rocketmq-delay-consume-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          producer-out-0:\n            producer:\n              group: output_1\n      bindings:\n        producer-out-0:\n          destination: delay\n        consumer-in-0:\n          destination: delay\n          group: delay-group\nlogging:\n  level:\n    org.springframework.context.support: debug\n```\n\n**code**\n\n```java\n@SpringBootApplication\npublic class RocketMQDelayConsumeApplication {\n   private static final Logger log = LoggerFactory\n         .getLogger(RocketMQDelayConsumeApplication.class);\n   @Autowired\n   private StreamBridge streamBridge;\n\n   public static void main(String[] args) {\n      SpringApplication.run(RocketMQDelayConsumeApplication.class, args);\n   }\n\n   @Bean\n   public ApplicationRunner producerDelay() {\n      return args -> {\n         for (int i = 0; i < 100; i++) {\n            String key = \"KEY\" + i;\n            Map<String, Object> headers = new HashMap<>();\n            headers.put(MessageConst.PROPERTY_KEYS, key);\n            headers.put(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID, i);\n   \t\t\t// Set the delay level 1~10\n\t\t\t headers.put(MessageConst.PROPERTY_DELAY_TIME_LEVEL, 2);\n            Message<SimpleMsg> msg = new GenericMessage(new SimpleMsg(\"Delay RocketMQ \" + i), headers);\n            streamBridge.send(\"producer-out-0\", msg);\n         }\n      };\n   }\n\n   @Bean\n   public Consumer<Message<SimpleMsg>> consumer() {\n      return msg -> {\n         log.info(Thread.currentThread().getName() + \" Consumer Receive New Messages: \" + msg.getPayload().getMsg());\n      };\n   }\n}\n```\n\n## Filter example\n\n### Create topic\n\n```sh\nsh bin/mqadmin updateTopic -n localhost:9876 -c DefaultCluster -t sql\n```\n\n### Example code\n\n**application.yml**\n\nRocketMQ stream binder supports filter by tag or sql, just setting `spring.cloud.stream.rocketmq.bindings.<channelName>.consumer.subscription`.\n\nTag example: `tag:red || blue`\n\nSql example: `sql:(color in ('red1', 'red2', 'red4') and price>3)`\n\nMore: [Filter](https://rocketmq.apache.org/docs/filter-by-sql92-example/)\n\n```yaml\nserver:\n  port: 28087\nspring:\n  application:\n    name: rocketmq-sql-consume-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          producer-out-0:\n            producer:\n              group: output_1\n          consumer-in-0:\n            consumer:\n              # tag: {@code tag1||tag2||tag3 }; sql: {@code 'color'='blue' AND 'price'>100 } .\n              subscription: sql:(color in ('red1', 'red2', 'red4') and price>3)\n      bindings:\n        producer-out-0:\n          destination: sql\n        consumer-in-0:\n          destination: sql\n          group: sql-group\nlogging:\n  level:\n    org.springframework.context.support: debug\n```\n\n**code**\n\n```java\n@SpringBootApplication\npublic class RocketMQSqlConsumeApplication {\n   private static final Logger log = LoggerFactory\n         .getLogger(RocketMQSqlConsumeApplication.class);\n   @Autowired\n   private StreamBridge streamBridge;\n   public static void main(String[] args) {\n      SpringApplication.run(RocketMQSqlConsumeApplication.class, args);\n   }\n\n   /**\n    * color array.\n    */\n   public static final String[] color = new String[] {\"red1\", \"red2\", \"red3\", \"red4\", \"red5\"};\n\n   /**\n    * price array.\n    */\n   public static final Integer[] price = new Integer[] {1, 2, 3, 4, 5};\n\n   @Bean\n   public ApplicationRunner producer() {\n      return args -> {\n         for (int i = 0; i < 100; i++) {\n            String key = \"KEY\" + i;\n            Map<String, Object> headers = new HashMap<>();\n            headers.put(MessageConst.PROPERTY_KEYS, key);\n            headers.put(\"color\", color[i % color.length]);\n            headers.put(\"price\", price[i % price.length]);\n            headers.put(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID, i);\n            Message<SimpleMsg> msg = new GenericMessage(new SimpleMsg(\"Hello RocketMQ \" + i), headers);\n            streamBridge.send(\"producer-out-0\", msg);\n         }\n      };\n   }\n\n   @Bean\n   public Consumer<Message<SimpleMsg>> consumer() {\n      return msg -> {\n         String colorHeaderKey = \"color\";\n         String priceHeaderKey = \"price\";\n         log.info(Thread.currentThread().getName() + \" Receive New Messages: \" + msg.getPayload().getMsg() + \" COLOR:\" +\n               msg.getHeaders().get(colorHeaderKey).toString() + \" \" +\n               \"PRICE: \" + msg.getHeaders().get(priceHeaderKey).toString());\n      };\n   }\n}\n```\n\n#### 常见问题\n\n- MQClientException: The broker does not support consumer to filter message by SQL92\n1. Modify RocketMQ server configuration file.\n   In the `conf/2m-2s-async/broker-a.properties` configuration file, add `enablePropertyFilter=true`.\n2. Restart mqbroker and specify the configuration file.\n   Specify the configuration file when `mqbroker` starts: `conf/2m-2s-async/broker-a.properties`, for example:\n```shell\nbin/mqbroker -n 127.0.0.1:9876 -c conf/2m-2s-async/broker-a.properties autoCreateTopicEnable=true  \n```\n\n## Transaction example\n\n### What is transactional message?\n\nRefer to [Transaction Example](https://rocketmq.apache.org/docs/transaction-example/).\n\n> It can be thought of as a two-phase commit message implementation to ensure eventual consistency in distributed system. Transactional message ensures that the execution of local transaction and the sending of message can be performed atomically.\n\n### Application\n\n> 1、 Transactional status\n>\n> There are three states for transactional message:\n> (1) TransactionStatus.CommitTransaction: commit transaction，it means that allow consumers to consume this message.\n> (2) TransactionStatus.RollbackTransaction: rollback transaction，it means that the message will be deleted and not allowed to consume.\n> (3) TransactionStatus.Unknown: intermediate state，it means that MQ is needed to check back to determine the status.\n\n### Create topic\n\n```sh\nsh bin/mqadmin updateTopic -n localhost:9876 -c DefaultCluster -t tx\n```\n\n### Example code\n\n**application.yml**\n\n```yaml\nserver:\n  port: 28088\nspring:\n  application:\n    name: rocketmq-tx-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          producer-out-0:\n            producer:\n              group: output_1\n              transactionListener: myTransactionListener\n              producerType: Trans\n      bindings:\n        producer-out-0:\n          destination: tx\n        consumer-in-0:\n          destination: tx\n          group: tx-group\nlogging:\n  level:\n    org.springframework.context.support: debug\n```\n\n**TransactionListenerImpl**\n\nTo execute local transaction.\n\n```java\n@Component(\"myTransactionListener\")\npublic class TransactionListenerImpl implements TransactionListener {\n\n\t@Override\n\tpublic LocalTransactionState executeLocalTransaction(Message msg, Object arg) {\n\t\tObject num = msg.getProperty(\"test\");\n\n\t\tif (\"1\".equals(num)) {\n\t\t\tSystem.out.println(\"executer: \" + new String(msg.getBody()) + \" unknown\");\n\t\t\treturn LocalTransactionState.UNKNOW;\n\t\t}\n\t\telse if (\"2\".equals(num)) {\n\t\t\tSystem.out.println(\"executer: \" + new String(msg.getBody()) + \" rollback\");\n\t\t\treturn LocalTransactionState.ROLLBACK_MESSAGE;\n\t\t}\n\t\tSystem.out.println(\"executer: \" + new String(msg.getBody()) + \" commit\");\n\t\treturn LocalTransactionState.COMMIT_MESSAGE;\n\t}\n\n\t@Override\n\tpublic LocalTransactionState checkLocalTransaction(MessageExt msg) {\n\t\tSystem.out.println(\"check: \" + new String(msg.getBody()));\n\t\treturn LocalTransactionState.COMMIT_MESSAGE;\n\t}\n\n}\n```\n\n**producer and consumer**\n\n```java\n@SpringBootApplication\npublic class RocketMQTxApplication {\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(RocketMQTxApplication.class);\n\t@Autowired\n\tprivate StreamBridge streamBridge;\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(RocketMQTxApplication.class, args);\n\t}\n\n\n\t@Bean\n\tpublic ApplicationRunner producer() {\n\t\treturn args -> {\n\t\t\tfor (int i = 1; i <= 4; i++) {\n\t\t\t\tMessageBuilder builder = MessageBuilder.withPayload(new SimpleMsg(\"Hello Tx msg \" + i));\n\t\t\t\tbuilder.setHeader(\"test\", String.valueOf(i))\n\t\t\t\t\t\t.setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON);\n\t\t\t\tbuilder.setHeader(RocketMQConst.USER_TRANSACTIONAL_ARGS, \"binder\");\n\t\t\t\tMessage<SimpleMsg> msg = builder.build();\n\t\t\t\tstreamBridge.send(\"producer-out-0\", msg);\n\t\t\t\tSystem.out.println(\"send Msg:\" + msg.toString());\n\t\t\t}\n\t\t};\n\t}\n\n\t@Bean\n\tpublic Consumer<Message<SimpleMsg>> consumer() {\n\t\treturn msg -> {\n\t\t\tObject arg = msg.getHeaders();\n\t\t\tlog.info(Thread.currentThread().getName() + \" Receive New Messages: \" + msg.getPayload().getMsg() + \" ARG:\"\n\t\t\t\t+ arg.toString());\n\t\t};\n\t}\n}\n```\n\n## Endpoint\n\nAdd dependency `spring-cloud-starter-stream-rocketmq` to your pom.xml file, and configure your endpoint security strategy.\n\n* Spring Boot1.x: Add configuration `management.security.enabled=false`    \n* Spring Boot2.x: Add configuration `management.endpoints.web.exposure.include=*`\n\nTo view the endpoint information, visit the following URLS:\n* Spring Boot1.x: Sentinel Endpoint URL is http://127.0.0.1:18083/rocketmq_binder.\n* Spring Boot2.x: Sentinel Endpoint URL is http://127.0.0.1:18083/actuator/rocketmq-binder.\n\nEndpoint will metrics some data like last send timestamp, sending or receive message successfully times or unsuccessfully times. \n\n```json\n{\n\t\"runtime\": {\n\t\t\"lastSend.timestamp\": 1542786623915\n\t},\n\t\"metrics\": {\n\t\t\"scs-rocketmq.consumer.test-topic.totalConsumed\": {\n\t\t\t\"count\": 11\n\t\t},\n\t\t\"scs-rocketmq.consumer.test-topic.totalConsumedFailures\": {\n\t\t\t\"count\": 0\n\t\t},\n\t\t\"scs-rocketmq.producer.test-topic.totalSentFailures\": {\n\t\t\t\"count\": 0\n\t\t},\n\t\t\"scs-rocketmq.consumer.test-topic.consumedPerSecond\": {\n\t\t\t\"count\": 11,\n\t\t\t\"fifteenMinuteRate\": 0.012163847780107841,\n\t\t\t\"fiveMinuteRate\": 0.03614605351360527,\n\t\t\t\"meanRate\": 0.3493213353657594,\n\t\t\t\"oneMinuteRate\": 0.17099243039490175\n\t\t},\n\t\t\"scs-rocketmq.producer.test-topic.totalSent\": {\n\t\t\t\"count\": 5\n\t\t},\n\t\t\"scs-rocketmq.producer.test-topic.sentPerSecond\": {\n\t\t\t\"count\": 5,\n\t\t\t\"fifteenMinuteRate\": 0.005540151995103271,\n\t\t\t\"fiveMinuteRate\": 0.01652854617838251,\n\t\t\t\"meanRate\": 0.10697493212602836,\n\t\t\t\"oneMinuteRate\": 0.07995558537067671\n\t\t},\n\t\t\"scs-rocketmq.producer.test-topic.sentFailuresPerSecond\": {\n\t\t\t\"count\": 0,\n\t\t\t\"fifteenMinuteRate\": 0.0,\n\t\t\t\"fiveMinuteRate\": 0.0,\n\t\t\t\"meanRate\": 0.0,\n\t\t\t\"oneMinuteRate\": 0.0\n\t\t},\n\t\t\"scs-rocketmq.consumer.test-topic.consumedFailuresPerSecond\": {\n\t\t\t\"count\": 0,\n\t\t\t\"fifteenMinuteRate\": 0.0,\n\t\t\t\"fiveMinuteRate\": 0.0,\n\t\t\t\"meanRate\": 0.0,\n\t\t\t\"oneMinuteRate\": 0.0\n\t\t}\n\t}\n}\n```\n\nNote: You should add [metrics-core dependency](https://mvnrepository.com/artifact/io.dropwizard.metrics/metrics-core) if you want to see metrics data. endpoint will show warning information if you don't add that dependency:\n\n```json\n{\n    \"warning\": \"please add metrics-core dependency, we use it for metrics\"\n}\n```\n\n## More\n\nFor more information about RocketMQ, see [RocketMQ Project](https://rocketmq.apache.org).\n\nIf you have any ideas or suggestions for Spring Cloud RocketMQ Binder, please don't hesitate to tell us by submitting github issues.\n\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-broadcast-example/rocketmq-broadcast-consumer1-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>rocketmq-broadcast-consumer1-example</artifactId>\n    <name>Spring Cloud Starter Stream Alibaba RocketMQ Broadcasting Consume Example Cosumer1</name>\n    <description>Example demonstrating how to broadcast consumption</description>\n\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-json</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>rocketmq-example-common</artifactId>\n            <version>${revision}</version>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-broadcast-example/rocketmq-broadcast-consumer1-example/src/main/java/com/alibaba/cloud/examples/broadcast/RocketMQBroadcastConsumer1Application.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.broadcast;\n\nimport java.util.function.Consumer;\n\nimport com.alibaba.cloud.examples.common.SimpleMsg;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.messaging.Message;\n\n/**\n * @author sorie\n */\n@SpringBootApplication\npublic class RocketMQBroadcastConsumer1Application {\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(RocketMQBroadcastConsumer1Application.class);\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(RocketMQBroadcastConsumer1Application.class, args);\n\t}\n\n\t@Bean\n\tpublic Consumer<Message<SimpleMsg>> consumer() {\n\t\treturn msg -> {\n\t\t\tlog.info(Thread.currentThread().getName() + \" Consumer1 Receive New Messages: \" + msg.getPayload().getMsg());\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-broadcast-example/rocketmq-broadcast-consumer1-example/src/main/resources/application.yml",
    "content": "server:\n  port: 28084\nspring:\n  application:\n    name: rocketmq-broadcast-consumer1-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          consumer-in-0:\n            consumer:\n              messageModel: BROADCASTING\n      bindings:\n        consumer-in-0:\n          destination: broadcast\n          group: broadcast-consumer\nlogging:\n  level:\n    org.springframework.context.support: debug\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-broadcast-example/rocketmq-broadcast-consumer2-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>rocketmq-broadcast-consumer2-example</artifactId>\n    <name>Spring Cloud Starter Stream Alibaba RocketMQ Broadcasting Consume Example Consumer2</name>\n    <description>Example demonstrating how to broadcast consumption</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-json</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>rocketmq-example-common</artifactId>\n            <version>${revision}</version>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-broadcast-example/rocketmq-broadcast-consumer2-example/src/main/java/com/alibaba/cloud/examples/broadcast/RocketMQBroadcastConsumer2Application.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.broadcast;\n\nimport java.util.function.Consumer;\n\nimport com.alibaba.cloud.examples.common.SimpleMsg;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.messaging.Message;\n\n/**\n * @author sorie\n */\n@SpringBootApplication\npublic class RocketMQBroadcastConsumer2Application {\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(RocketMQBroadcastConsumer2Application.class);\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(RocketMQBroadcastConsumer2Application.class, args);\n\t}\n\n\t@Bean\n\tpublic Consumer<Message<SimpleMsg>> consumer() {\n\t\treturn msg -> {\n\t\t\tlog.info(Thread.currentThread().getName() + \" Consumer2 Receive New Messages: \" + msg.getPayload().getMsg());\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-broadcast-example/rocketmq-broadcast-consumer2-example/src/main/resources/application.yml",
    "content": "server:\n  port: 28083\nspring:\n  application:\n    name: rocketmq-broadcast-consumer2-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          consumer-in-0:\n            consumer:\n              messageModel: BROADCASTING\n      bindings:\n        consumer-in-0:\n          destination: broadcast\n          group: broadcast-consumer\nlogging:\n  level:\n    org.springframework.context.support: debug\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-broadcast-example/rocketmq-broadcast-producer-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>rocketmq-broadcast-producer-example</artifactId>\n    <name>Spring Cloud Starter Stream Alibaba RocketMQ Broadcasting Consume Example Producer</name>\n    <description>Example demonstrating how to use rocketmq to produce</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-json</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>rocketmq-example-common</artifactId>\n            <version>${revision}</version>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-broadcast-example/rocketmq-broadcast-producer-example/src/main/java/com/alibaba/cloud/examples/broadcast/RocketMQBroadcastProducerApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.broadcast;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport com.alibaba.cloud.examples.common.SimpleMsg;\nimport org.apache.rocketmq.common.message.MessageConst;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.ApplicationRunner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.stream.function.StreamBridge;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.messaging.Message;\nimport org.springframework.messaging.support.GenericMessage;\n\n\n/**\n * @author sorie\n */\n@SpringBootApplication\npublic class RocketMQBroadcastProducerApplication {\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(RocketMQBroadcastProducerApplication.class);\n\t@Autowired\n\tprivate StreamBridge streamBridge;\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(RocketMQBroadcastProducerApplication.class, args);\n\t}\n\n\t@Bean\n\tpublic ApplicationRunner producer() {\n\t\treturn args -> {\n\t\t\tfor (int i = 0; i < 100; i++) {\n\t\t\t\tString key = \"KEY\" + i;\n\t\t\t\tMap<String, Object> headers = new HashMap<>();\n\t\t\t\theaders.put(MessageConst.PROPERTY_KEYS, key);\n\t\t\t\theaders.put(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID, i);\n\t\t\t\tMessage<SimpleMsg> msg = new GenericMessage<SimpleMsg>(new SimpleMsg(\"Hello RocketMQ \" + i), headers);\n\t\t\t\tstreamBridge.send(\"producer-out-0\", msg);\n\t\t\t}\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-broadcast-example/rocketmq-broadcast-producer-example/src/main/resources/application.yml",
    "content": "server:\n  port: 28085\nspring:\n  application:\n    name: rocketmq-broadcast-producer-example\n  cloud:\n    stream:\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          producer-out-0:\n            producer:\n              group: output_1\n      bindings:\n        producer-out-0:\n          destination: broadcast\nlogging:\n  level:\n    org.springframework.context.support: debug\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-comprehensive-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>rocketmq-comprehensive-example</artifactId>\n    <name>Spring Cloud Starter Stream Alibaba RocketMQ Comprehensive Example</name>\n    <description>Example demonstrating how to use rocketmq to produce, process and consume</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-json</artifactId>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-comprehensive-example/src/main/java/com/alibaba/cloud/examples/RocketMQComprehensiveApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport java.time.Duration;\nimport java.util.Arrays;\nimport java.util.function.Consumer;\nimport java.util.function.Function;\nimport java.util.function.Supplier;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport reactor.core.publisher.Flux;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.integration.support.StringObjectMapBuilder;\n\n/**\n * @author freeman\n */\n@SpringBootApplication\npublic class RocketMQComprehensiveApplication {\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(RocketMQComprehensiveApplication.class);\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(RocketMQComprehensiveApplication.class, args);\n\t}\n\n\t@Bean\n\tpublic Supplier<Flux<User>> producer() {\n\t\treturn () -> Flux.interval(Duration.ofSeconds(2)).map(id -> {\n\t\t\tUser user = new User();\n\t\t\tuser.setId(id.toString());\n\t\t\tuser.setName(\"freeman\");\n\t\t\tuser.setMeta(new StringObjectMapBuilder()\n\t\t\t\t\t.put(\"hobbies\", Arrays.asList(\"movies\", \"songs\")).put(\"age\", 21)\n\t\t\t\t\t.get());\n\t\t\treturn user;\n\t\t}).log();\n\t}\n\n\t@Bean\n\tpublic Function<Flux<User>, Flux<User>> processor() {\n\t\treturn flux -> flux.map(user -> {\n\t\t\tuser.setId(String.valueOf(\n\t\t\t\t\tLong.parseLong(user.getId()) * Long.parseLong(user.getId())));\n\t\t\tuser.setName(\"not freeman\");\n\t\t\tuser.getMeta().put(\"hobbies\", Arrays.asList(\"programming\"));\n\t\t\treturn user;\n\t\t});\n\t}\n\n\t@Bean\n\tpublic Consumer<User> consumer() {\n\t\treturn num -> log.info(num.toString());\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-comprehensive-example/src/main/java/com/alibaba/cloud/examples/User.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport java.util.Map;\n\n/**\n * @author freeman\n */\npublic class User {\n\tprivate String id;\n\tprivate String name;\n\tprivate Map<String, Object> meta;\n\n\tpublic String getId() {\n\t\treturn id;\n\t}\n\n\tpublic void setId(String id) {\n\t\tthis.id = id;\n\t}\n\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\tpublic void setName(String name) {\n\t\tthis.name = name;\n\t}\n\n\tpublic Map<String, Object> getMeta() {\n\t\treturn meta;\n\t}\n\n\tpublic void setMeta(Map<String, Object> meta) {\n\t\tthis.meta = meta;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"User{\" + \"id='\" + id + '\\'' + \", name='\" + name + '\\'' + \", meta=\" + meta\n\t\t\t\t+ '}';\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-comprehensive-example/src/main/resources/application.yml",
    "content": "server:\n  port: 28082\nspring:\n  application:\n    name: rocketmq-comprehensive-example\n  cloud:\n    function:\n      definition: producer;consumer;processor\n    stream:\n      rocketmq:\n        binder:\n          name-server: 127.0.0.1:9876\n        bindings:\n          # TODO producer must have a group, need optimization !!!\n          producer-out-0:\n            producer:\n              group: output_1\n          processor-out-0:\n            producer:\n              group: output_2\n\n      bindings:\n        producer-out-0:\n          destination: num\n        processor-out-0:\n          destination: square\n        processor-in-0:\n          destination: num\n          group: processor_group\n        consumer-in-0:\n          destination: square\n          group: consumer_group\n\nlogging:\n  level:\n    org.springframework.context.support: debug\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-delay-consume-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>rocketmq-delay-consume-example</artifactId>\n    <name>Spring Cloud Starter Stream Alibaba RocketMQ Delay Consume Example</name>\n    <description>Example demonstrating how to use rocketmq to delay consume</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>rocketmq-example-common</artifactId>\n            <version>${revision}</version>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-delay-consume-example/src/main/java/com/alibaba/cloud/examples/delay/RocketMQDelayConsumeApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.delay;\n\nimport java.time.LocalDateTime;\nimport java.time.format.DateTimeFormatter;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.function.Consumer;\n\nimport com.alibaba.cloud.examples.common.SimpleMsg;\nimport org.apache.rocketmq.common.message.MessageConst;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.ApplicationRunner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.stream.function.StreamBridge;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.messaging.Message;\nimport org.springframework.messaging.support.GenericMessage;\n/**\n * @author sorie\n */\n@SpringBootApplication\npublic class RocketMQDelayConsumeApplication {\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(RocketMQDelayConsumeApplication.class);\n\n\tprivate static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss.SSS\");\n\n\tprivate static LocalDateTime sendTime;\n\n\t@Autowired\n\tprivate StreamBridge streamBridge;\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(RocketMQDelayConsumeApplication.class, args);\n\t}\n\n\t/**\n\t * Produce delay messages.\n\t */\n\t@Bean\n\tpublic ApplicationRunner producerDelay() {\n\t\treturn args -> {\n\t\t\tfor (int i = 0; i < 100; i++) {\n\t\t\t\tString key = \"KEY\" + i;\n\t\t\t\tMap<String, Object> headers = new HashMap<>();\n\t\t\t\theaders.put(MessageConst.PROPERTY_KEYS, key);\n\t\t\t\theaders.put(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID, i);\n\t\t\t\theaders.put(MessageConst.PROPERTY_DELAY_TIME_LEVEL, 2);\n\t\t\t\tMessage<SimpleMsg> msg = new GenericMessage(new SimpleMsg(\"Delay RocketMQ \" + i), headers);\n\t\t\t\tstreamBridge.send(\"producer-out-0\", msg);\n\t\t\t}\n\t\t\tsendTime = LocalDateTime.now();\n\t\t\tlog.info(\"All 100 messages sent at {}\", sendTime.format(FORMATTER));\n\t\t};\n\t}\n\n\t@Bean\n\tpublic Consumer<Message<SimpleMsg>> consumer() {\n\t\treturn msg -> {\n\t\t\tlog.info(Thread.currentThread().getName() + \" Consumer Receive New Messages: \" + msg.getPayload().getMsg() + \". Delay time(s): \" + (LocalDateTime.now().getSecond() - sendTime.getSecond()));\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-delay-consume-example/src/main/resources/application.yml",
    "content": "server:\n  port: 28086\nspring:\n  application:\n    name: rocketmq-delay-consume-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          producer-out-0:\n            producer:\n              group: output_1\n      bindings:\n        producer-out-0:\n          destination: delay\n        consumer-in-0:\n          destination: delay\n          group: delay-group\nlogging:\n  level:\n    org.springframework.context.support: debug\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-example-common/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>rocketmq-example-common</artifactId>\n    <name>Spring Cloud Starter Stream Alibaba RocketMQ Example COMMON</name>\n    <description>Some rocketMQ exmaple common codes</description>\n    <packaging>jar</packaging>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-example-common/src/main/java/com/alibaba/cloud/examples/common/SimpleMsg.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.common;\n\n/**\n * @author sorie\n */\npublic class SimpleMsg {\n\n\tprivate String msg;\n\n\tpublic SimpleMsg() {\n\t}\n\n\tpublic SimpleMsg(String msg) {\n\t\tthis.msg = msg;\n\t}\n\n\tpublic String getMsg() {\n\t\treturn msg;\n\t}\n\n\tpublic void setMsg(String msg) {\n\t\tthis.msg = msg;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-example-common/src/main/resources/application.yml",
    "content": "server:\n  port: 28087\nspring:\n  application:\n    name: rocketmq-sql-consume-example\n  cloud:\n    stream:\n      function:\n        definition: producer;consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          producer-out-0:\n            producer:\n              group: output_1\n          consumer-in-0:\n            consumer:\n#             tag: {@code tag1||tag2||tag3 }; sql: {@code 'color'='blue' AND 'price'>100 } .\n              subscription: sql:(color in ('red1', 'red2', 'red4') and price>3)\n      bindings:\n        producer-out-0:\n          destination: sql\n        consumer-in-0:\n          destination: sql\n          group: sql-group\nlogging:\n  level:\n    org.springframework.context.support: debug\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-orderly-consume-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>rocketmq-orderly-consume-example</artifactId>\n    <name>Spring Cloud Starter Stream Alibaba RocketMQ Orderly Consume Example</name>\n    <description>Example demonstrating how to use rocketmq to produce, and consume orderly</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-json</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>rocketmq-example-common</artifactId>\n            <version>${revision}</version>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-orderly-consume-example/src/main/java/com/alibaba/cloud/examples/orderly/OrderlyMessageQueueSelector.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.orderly;\n\nimport java.util.List;\n\nimport org.apache.rocketmq.client.producer.MessageQueueSelector;\nimport org.apache.rocketmq.common.message.Message;\nimport org.apache.rocketmq.common.message.MessageConst;\nimport org.apache.rocketmq.common.message.MessageQueue;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.messaging.MessageHeaders;\nimport org.springframework.stereotype.Component;\n\n\n/**\n * @author sorie\n */\n@Component\npublic class OrderlyMessageQueueSelector implements MessageQueueSelector {\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(OrderlyMessageQueueSelector.class);\n\n\t/**\n\t * to select a fixed queue by id.\n\t * @param mqs all message queues of this topic.\n\t * @param msg mq message.\n\t * @param arg mq arguments.\n\t * @return message queue selected.\n\t */\n\t@Override\n\tpublic MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {\n\t\tInteger id = (Integer) ((MessageHeaders) arg).get(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID);\n\t\tint index = id % RocketMQOrderlyConsumeApplication.tags.length % mqs.size();\n\t\treturn mqs.get(index);\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-orderly-consume-example/src/main/java/com/alibaba/cloud/examples/orderly/RocketMQOrderlyConsumeApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.orderly;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.function.Consumer;\n\nimport com.alibaba.cloud.examples.common.SimpleMsg;\nimport com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQMessageConverterSupport;\nimport org.apache.rocketmq.common.message.MessageConst;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.ApplicationRunner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.stream.function.StreamBridge;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.messaging.Message;\nimport org.springframework.messaging.support.GenericMessage;\n/**\n * @author sorie\n */\n@SpringBootApplication\npublic class RocketMQOrderlyConsumeApplication {\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(RocketMQOrderlyConsumeApplication.class);\n\n\t@Autowired\n\tprivate StreamBridge streamBridge;\n\n\t/***\n\t * tag array.\n\t */\n\tpublic static final String[] tags = new String[] {\"TagA\", \"TagB\", \"TagC\", \"TagD\", \"TagE\"};\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(RocketMQOrderlyConsumeApplication.class, args);\n\t}\n\n\t@Bean\n\tpublic ApplicationRunner producer() {\n\t\treturn args -> {\n\t\t\tfor (int i = 0; i < 100; i++) {\n\t\t\t\tString key = \"KEY\" + i;\n\t\t\t\tMap<String, Object> headers = new HashMap<>();\n\t\t\t\theaders.put(MessageConst.PROPERTY_KEYS, key);\n\t\t\t\theaders.put(MessageConst.PROPERTY_TAGS, tags[i % tags.length]);\n\t\t\t\theaders.put(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID, i);\n\t\t\t\tMessage<SimpleMsg> msg = new GenericMessage(new SimpleMsg(\"Hello RocketMQ \" + i), headers);\n\t\t\t\tstreamBridge.send(\"producer-out-0\", msg);\n\t\t\t}\n\t\t};\n\t}\n\n\t@Bean\n\tpublic Consumer<Message<SimpleMsg>> consumer() {\n\t\treturn msg -> {\n\t\t\tString tagHeaderKey = RocketMQMessageConverterSupport.toRocketHeaderKey(\n\t\t\t\t\tMessageConst.PROPERTY_TAGS).toString();\n\t\t\tlog.info(Thread.currentThread().getName() + \" Receive New Messages: \" + msg.getPayload().getMsg() + \" TAG:\" +\n\t\t\t\t\tmsg.getHeaders().get(tagHeaderKey).toString());\n\t\t\ttry {\n\t\t\t\tThread.sleep(100);\n\t\t\t}\n\t\t\tcatch (InterruptedException ignored) {\n\t\t\t}\n\t\t};\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-orderly-consume-example/src/main/resources/application.yml",
    "content": "server:\n  port: 28082\nspring:\n  application:\n    name: rocketmq-orderly-consume-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          producer-out-0:\n            producer:\n              group: output_1\n              messageQueueSelector: orderlyMessageQueueSelector\n          consumer-in-0:\n            consumer:\n              # tag: {@code tag1||tag2||tag3 }; sql: {@code 'color'='blue' AND 'price'>100 } .\n              subscription: 'TagA || TagC || TagD'\n              push:\n                orderly: true\n      bindings:\n        producer-out-0:\n          destination: orderly\n        consumer-in-0:\n          destination: orderly\n          group: orderly-consumer\n\nlogging:\n  level:\n    org.springframework.context.support: debug\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-pollable-consume-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>rocketmq-pollable-consume-example</artifactId>\n    <name>Spring Cloud Starter Stream Alibaba RocketMQ PollableMessageSource Consume Example</name>\n    <description>Example demonstrating how to use rocketmq to produce, and consume by PollableMessageSource</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-json</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>rocketmq-example-common</artifactId>\n            <version>${revision}</version>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-pollable-consume-example/src/main/java/com/alibaba/cloud/examples/pollable/RocketMQPollableConsumeApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.pollable;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport com.alibaba.cloud.examples.common.SimpleMsg;\nimport org.apache.rocketmq.common.message.MessageConst;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.ApplicationRunner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.stream.binder.PollableMessageSource;\nimport org.springframework.cloud.stream.function.StreamBridge;\nimport org.springframework.context.ConfigurableApplicationContext;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.core.ParameterizedTypeReference;\nimport org.springframework.messaging.Message;\nimport org.springframework.messaging.support.GenericMessage;\n\n/**\n * @author sorie\n */\n@SpringBootApplication\npublic class RocketMQPollableConsumeApplication {\n\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(RocketMQPollableConsumeApplication.class);\n\n\t@Autowired\n\tprivate StreamBridge streamBridge;\n\n\tpublic static void main(String[] args) {\n\t\tConfigurableApplicationContext context = SpringApplication.run(RocketMQPollableConsumeApplication.class, args);\n\t\tPollableMessageSource destIn = context.getBean(PollableMessageSource.class);\n\t\tnew Thread(() -> {\n\t\t\twhile (true) {\n\t\t\t\ttry {\n\t\t\t\t\tif (!destIn.poll((m) -> {\n\t\t\t\t\t\tSimpleMsg newPayload = (SimpleMsg) m.getPayload();\n\t\t\t\t\t\tSystem.out.println(newPayload.getMsg());\n\t\t\t\t\t}, new ParameterizedTypeReference<SimpleMsg>() {\n\t\t\t\t\t})) {\n\t\t\t\t\t\tThread.sleep(1000);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcatch (Exception e) {\n\t\t\t\t\t// handle failure\n\t\t\t\t}\n\t\t\t}\n\t\t}).start();\n\t}\n\n\t@Bean\n\tpublic ApplicationRunner producer() {\n\t\treturn args -> {\n\t\t\tfor (int i = 0; i < 100; i++) {\n\t\t\t\tString key = \"KEY\" + i;\n\t\t\t\tMap<String, Object> headers = new HashMap<>();\n\t\t\t\theaders.put(MessageConst.PROPERTY_KEYS, key);\n\t\t\t\tMessage<SimpleMsg> msg = new GenericMessage(\n\t\t\t\t\t\tnew SimpleMsg(\"Hello RocketMQ \" + i), headers);\n\t\t\t\tstreamBridge.send(\"producer-out-0\", msg);\n\t\t\t}\n\t\t};\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-pollable-consume-example/src/main/resources/application.yml",
    "content": "server:\n  port: 28089\nspring:\n  application:\n    name: rocketmq-pollable-consume-example\n  cloud:\n    stream:\n      pollable-source: pollable\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          producer-out-0:\n            producer:\n              group: output_1\n      bindings:\n        producer-out-0:\n          destination: pollable\n        pollable-in-0:\n          destination: pollable\nlogging:\n  level:\n    org.springframework.context.support: debug\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-sql-consume-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>rocketmq-sql-consume-example</artifactId>\n    <name>Spring Cloud Starter Stream Alibaba RocketMQ Sql Consume Example</name>\n    <description>Example demonstrating how to use rocketmq to filter message by sql</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>rocketmq-example-common</artifactId>\n            <version>${revision}</version>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-sql-consume-example/src/main/java/com/alibaba/cloud/examples/sql/RocketMQSqlConsumeApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.sql;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.function.Consumer;\n\nimport com.alibaba.cloud.examples.common.SimpleMsg;\nimport org.apache.rocketmq.common.message.MessageConst;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.ApplicationRunner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.stream.function.StreamBridge;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.messaging.Message;\nimport org.springframework.messaging.support.GenericMessage;\n/**\n * @author sorie\n */\n@SpringBootApplication\npublic class RocketMQSqlConsumeApplication {\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(RocketMQSqlConsumeApplication.class);\n\t@Autowired\n\tprivate StreamBridge streamBridge;\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(RocketMQSqlConsumeApplication.class, args);\n\t}\n\n\t/**\n\t * color array.\n\t */\n\tpublic static final String[] color = new String[] {\"red1\", \"red2\", \"red3\", \"red4\", \"red5\"};\n\n\t/**\n\t * price array.\n\t */\n\tpublic static final Integer[] price = new Integer[] {1, 2, 3, 4, 5};\n\n\t@Bean\n\tpublic ApplicationRunner producer() {\n\t\treturn args -> {\n\t\t\tfor (int i = 0; i < 100; i++) {\n\t\t\t\tString key = \"KEY\" + i;\n\t\t\t\tMap<String, Object> headers = new HashMap<>();\n\t\t\t\theaders.put(MessageConst.PROPERTY_KEYS, key);\n\t\t\t\theaders.put(\"color\", color[i % color.length]);\n\t\t\t\theaders.put(\"price\", price[i % price.length]);\n\t\t\t\theaders.put(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID, i);\n\t\t\t\tMessage<SimpleMsg> msg = new GenericMessage(new SimpleMsg(\"Hello RocketMQ \" + i), headers);\n\t\t\t\tstreamBridge.send(\"producer-out-0\", msg);\n\t\t\t}\n\t\t};\n\t}\n\n\t@Bean\n\tpublic Consumer<Message<SimpleMsg>> consumer() {\n\t\treturn msg -> {\n\t\t\tString colorHeaderKey = \"color\";\n\t\t\tString priceHeaderKey = \"price\";\n\t\t\tlog.info(Thread.currentThread().getName() + \" Receive New Messages: \" + msg.getPayload().getMsg() + \" COLOR:\" +\n\t\t\t\t\tmsg.getHeaders().get(colorHeaderKey).toString() + \" \" +\n\t\t\t\t\t\"PRICE: \" + msg.getHeaders().get(priceHeaderKey).toString());\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-sql-consume-example/src/main/resources/application.yml",
    "content": "server:\n  port: 28087\nspring:\n  application:\n    name: rocketmq-sql-consume-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          producer-out-0:\n            producer:\n              group: output_1\n          consumer-in-0:\n            consumer:\n#             tag: {@code tag1||tag2||tag3 }; sql: {@code 'color'='blue' AND 'price'>100 } .\n              subscription: sql:(color in ('red1', 'red2', 'red4') and price>3)\n      bindings:\n        producer-out-0:\n          destination: sql\n        consumer-in-0:\n          destination: sql\n          group: sql-group\nlogging:\n  level:\n    org.springframework.context.support: debug\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-tx-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>rocketmq-tx-example</artifactId>\n    <name>Spring Cloud Starter Stream Alibaba RocketMQ Transaction message Example</name>\n    <description>Example demonstrating how to send and consume transaction messages in rocketmq</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>rocketmq-example-common</artifactId>\n            <version>${revision}</version>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-tx-example/src/main/java/com/alibaba/cloud/examples/tx/RocketMQTxApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.tx;\n\nimport java.util.function.Consumer;\n\nimport com.alibaba.cloud.examples.common.SimpleMsg;\nimport com.alibaba.cloud.stream.binder.rocketmq.constant.RocketMQConst;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.ApplicationRunner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.stream.function.StreamBridge;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.messaging.Message;\nimport org.springframework.messaging.MessageHeaders;\nimport org.springframework.messaging.support.MessageBuilder;\nimport org.springframework.util.MimeTypeUtils;\n\n/**\n * @author sorie\n */\n@SpringBootApplication\npublic class RocketMQTxApplication {\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(RocketMQTxApplication.class);\n\t@Autowired\n\tprivate StreamBridge streamBridge;\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(RocketMQTxApplication.class, args);\n\t}\n\n\n\t@Bean\n\tpublic ApplicationRunner producer() {\n\t\treturn args -> {\n\t\t\tfor (int i = 1; i <= 4; i++) {\n\t\t\t\tMessageBuilder builder = MessageBuilder.withPayload(new SimpleMsg(\"Hello Tx msg \" + i));\n\t\t\t\tbuilder.setHeader(\"test\", String.valueOf(i))\n\t\t\t\t\t\t.setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON);\n\t\t\t\tbuilder.setHeader(RocketMQConst.USER_TRANSACTIONAL_ARGS, \"binder\");\n\t\t\t\tMessage<SimpleMsg> msg = builder.build();\n\t\t\t\tstreamBridge.send(\"producer-out-0\", msg);\n\t\t\t\tSystem.out.println(\"send Msg:\" + msg.toString());\n\t\t\t}\n\t\t};\n\t}\n\n\t@Bean\n\tpublic Consumer<Message<SimpleMsg>> consumer() {\n\t\treturn msg -> {\n\t\t\tObject arg = msg.getHeaders();\n\t\t\tlog.info(Thread.currentThread().getName() + \" Receive New Messages: \" + msg.getPayload().getMsg() + \" ARG:\"\n\t\t\t\t+ arg.toString());\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-tx-example/src/main/java/com/alibaba/cloud/examples/tx/TransactionListenerImpl.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.tx;\n\nimport org.apache.rocketmq.client.producer.LocalTransactionState;\nimport org.apache.rocketmq.client.producer.TransactionListener;\nimport org.apache.rocketmq.common.message.Message;\nimport org.apache.rocketmq.common.message.MessageExt;\n\nimport org.springframework.stereotype.Component;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@Component(\"myTransactionListener\")\npublic class TransactionListenerImpl implements TransactionListener {\n\n\t/**\n\t * Execute local transaction.\n\t * @param msg messages\n\t * @param arg message args\n\t * @return Transaction state\n\t */\n\t@Override\n\tpublic LocalTransactionState executeLocalTransaction(Message msg, Object arg) {\n\t\tObject num = msg.getProperty(\"test\");\n\n\t\tif (\"1\".equals(num)) {\n\t\t\tSystem.out.println(\"executer: \" + new String(msg.getBody()) + \" unknown\");\n\t\t\treturn LocalTransactionState.UNKNOW;\n\t\t}\n\t\telse if (\"2\".equals(num)) {\n\t\t\tSystem.out.println(\"executer: \" + new String(msg.getBody()) + \" rollback\");\n\t\t\treturn LocalTransactionState.ROLLBACK_MESSAGE;\n\t\t}\n\t\tSystem.out.println(\"executer: \" + new String(msg.getBody()) + \" commit\");\n\t\treturn LocalTransactionState.COMMIT_MESSAGE;\n\t}\n\n\t/**\n\t * MQ check back local transaction states.\n\t * @param msg messages\n\t * @return Transaction state\n\t */\n\t@Override\n\tpublic LocalTransactionState checkLocalTransaction(MessageExt msg) {\n\t\tSystem.out.println(\"check: \" + new String(msg.getBody()));\n\t\treturn LocalTransactionState.COMMIT_MESSAGE;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/rocketmq-example/rocketmq-tx-example/src/main/resources/application.yml",
    "content": "server:\n  port: 28088\nspring:\n  application:\n    name: rocketmq-tx-example\n  cloud:\n    stream:\n      function:\n        definition: consumer;\n      rocketmq:\n        binder:\n          name-server: localhost:9876\n        bindings:\n          producer-out-0:\n            producer:\n              group: output_1\n              transactionListener: myTransactionListener\n              producerType: Trans\n      bindings:\n        producer-out-0:\n          destination: tx\n        consumer-in-0:\n          destination: tx\n          group: tx-group\nlogging:\n  level:\n    org.springframework.context.support: debug\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/account-service/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <groupId>com.alibaba.cloud</groupId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>account-service</artifactId>\n    <name>Spring Cloud Starter Alibaba Seata Example - Account Service</name>\n    <packaging>jar</packaging>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-jdbc</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.mysql</groupId>\n            <artifactId>mysql-connector-j</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.apache.logging.log4j</groupId>\n            <artifactId>log4j-core</artifactId>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/account-service/src/main/java/com/alibaba/cloud/examples/AccountApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * @author xiaojing\n */\n@SpringBootApplication\npublic class AccountApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(AccountApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/account-service/src/main/java/com/alibaba/cloud/examples/AccountController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport java.util.Random;\n\nimport org.apache.seata.core.context.RootContext;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author xiaojing\n */\n@RestController\npublic class AccountController {\n\n\tprivate static final Logger LOGGER = LoggerFactory.getLogger(AccountController.class);\n\n\tprivate static final String SUCCESS = \"SUCCESS\";\n\n\tprivate static final String FAIL = \"FAIL\";\n\n\tprivate final JdbcTemplate jdbcTemplate;\n\n\tprivate Random random;\n\n\tpublic AccountController(JdbcTemplate jdbcTemplate) {\n\t\tthis.jdbcTemplate = jdbcTemplate;\n\t\tthis.random = new Random();\n\t}\n\n\t@PostMapping(value = \"/account\", produces = \"application/json\")\n\tpublic String account(String userId, int money) {\n\t\tLOGGER.info(\"Account Service ... xid: \" + RootContext.getXID());\n\n\t\tif (random.nextBoolean()) {\n\t\t\tthrow new RuntimeException(\"this is a mock Exception\");\n\t\t}\n\n\t\tint result = jdbcTemplate.update(\n\t\t\t\t\"update account_tbl set money = money - ? where user_id = ?\",\n\t\t\t\tnew Object[] { money, userId });\n\t\tLOGGER.info(\"Account Service End ... \");\n\t\tif (result == 1) {\n\t\t\treturn SUCCESS;\n\t\t}\n\t\treturn FAIL;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/account-service/src/main/java/com/alibaba/cloud/examples/DatabaseConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport javax.sql.DataSource;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.jdbc.core.JdbcTemplate;\n\n/**\n * @author xiaojing\n */\n@Configuration\npublic class DatabaseConfiguration {\n\n//  druid don't support GraalVM now because of there is CGlib proxy\n//\t@Bean\n//\t@Primary\n//\t@ConfigurationProperties(\"spring.datasource\")\n//\tpublic DataSource storageDataSource() {\n//\t\treturn new DruidDataSource();\n//\t}\n\n\t@Bean\n\tpublic JdbcTemplate jdbcTemplate(DataSource dataSource) {\n\t\tJdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);\n\n\t\tjdbcTemplate.update(\"delete from account_tbl where user_id = 'U100001'\");\n\t\tjdbcTemplate.update(\n\t\t\t\t\"insert into account_tbl(user_id, money) values ('U100001', 10000)\");\n\n\t\treturn jdbcTemplate;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/account-service/src/main/resources/application.yml",
    "content": "base:\n  config:\n    mdb:\n      hostname: 127.0.0.1 #your mysql server ip address\n      dbname: seata #your database name for test\n      port: 3306 #your mysql server listening port\n      username: 'root' #your mysql server username\n      password: 'root' #your mysql server password\n\nserver:\n  port: 18084\n\nspring:\n  cloud:\n    nacos:\n      discovery:\n        server-addr: 127.0.0.1:8848\n        username: 'nacos'\n        password: 'nacos'\n  application:\n    name: account-service\n  main:\n    allow-bean-definition-overriding: true\n  datasource:\n    name: storageDataSource\n#    druid don't support GraalVM now because of there is CGlib proxy\n#    type: com.alibaba.druid.pool.DruidDataSource\n    driver-class-name: com.mysql.cj.jdbc.Driver\n    url: jdbc:mysql://${base.config.mdb.hostname}:${base.config.mdb.port}/${base.config.mdb.dbname}?useSSL=false&serverTimezone=UTC\n    username: ${base.config.mdb.username}\n    password: ${base.config.mdb.password}\n#    druid:\n#      max-active: 20\n#      min-idle: 2\n#      initial-size: 2\n\nseata:\n  enabled: true\n  application-id: ${spring.application.name}\n\n  tx-service-group: ${spring.application.name}-tx-group\n  config:\n    type: nacos\n\n    nacos:\n      serverAddr: 127.0.0.1:8848\n      dataId: \"seata.properties\"\n      group: SEATA_GROUP\n      username: 'nacos'\n      password: 'nacos'\n  registry:\n    type: nacos\n    nacos:\n      application: seata-server\n      server-addr: 127.0.0.1:8848\n      cluster: default\n      group: SEATA_GROUP\n      username: 'nacos'\n      password: 'nacos'\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/all.sql",
    "content": "-- -------------------------------- Create undo_ Log table --------------------------------\n-- Seata AT Mode Need to use undo_ Log table.\nCREATE TABLE `undo_log` (\n                            `id` bigint(20) NOT NULL AUTO_INCREMENT,\n                            `branch_id` bigint(20) NOT NULL,\n                            `xid` varchar(100) NOT NULL,\n                            `context` varchar(128) NOT NULL,\n                            `rollback_info` longblob NOT NULL,\n                            `log_status` int(11) NOT NULL,\n                            `log_created` datetime NOT NULL,\n                            `log_modified` datetime NOT NULL,\n                            `ext` varchar(100) DEFAULT NULL,\n                            PRIMARY KEY (`id`),\n                            UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)\n) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;\n\n-- -------------------------------- The script used when storeMode is 'db' --------------------------------\n-- the table to store GlobalSession data\nCREATE TABLE IF NOT EXISTS `global_table`\n(\n    `xid`                       VARCHAR(128) NOT NULL,\n    `transaction_id`            BIGINT,\n    `status`                    TINYINT      NOT NULL,\n    `application_id`            VARCHAR(32),\n    `transaction_service_group` VARCHAR(32),\n    `transaction_name`          VARCHAR(128),\n    `timeout`                   INT,\n    `begin_time`                BIGINT,\n    `application_data`          VARCHAR(2000),\n    `gmt_create`                DATETIME,\n    `gmt_modified`              DATETIME,\n    PRIMARY KEY (`xid`),\n    KEY `idx_status_gmt_modified` (`status` , `gmt_modified`),\n    KEY `idx_transaction_id` (`transaction_id`)\n    ) ENGINE = InnoDB\n    DEFAULT CHARSET = utf8mb4;\n\n-- the table to store BranchSession data\nCREATE TABLE IF NOT EXISTS `branch_table`\n(\n    `branch_id`         BIGINT       NOT NULL,\n    `xid`               VARCHAR(128) NOT NULL,\n    `transaction_id`    BIGINT,\n    `resource_group_id` VARCHAR(32),\n    `resource_id`       VARCHAR(256),\n    `branch_type`       VARCHAR(8),\n    `status`            TINYINT,\n    `client_id`         VARCHAR(64),\n    `application_data`  VARCHAR(2000),\n    `gmt_create`        DATETIME(6),\n    `gmt_modified`      DATETIME(6),\n    PRIMARY KEY (`branch_id`),\n    KEY `idx_xid` (`xid`)\n    ) ENGINE = InnoDB\n    DEFAULT CHARSET = utf8mb4;\n\n-- the table to store lock data\nCREATE TABLE IF NOT EXISTS `lock_table`\n(\n    `row_key`        VARCHAR(128) NOT NULL,\n    `xid`            VARCHAR(128),\n    `transaction_id` BIGINT,\n    `branch_id`      BIGINT       NOT NULL,\n    `resource_id`    VARCHAR(256),\n    `table_name`     VARCHAR(32),\n    `pk`             VARCHAR(36),\n    `status`         TINYINT      NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',\n    `gmt_create`     DATETIME,\n    `gmt_modified`   DATETIME,\n    PRIMARY KEY (`row_key`),\n    KEY `idx_status` (`status`),\n    KEY `idx_branch_id` (`branch_id`),\n    KEY `idx_xid_and_branch_id` (`xid` , `branch_id`)\n    ) ENGINE = InnoDB\n    DEFAULT CHARSET = utf8mb4;\n\nCREATE TABLE IF NOT EXISTS `distributed_lock`\n(\n    `lock_key`       CHAR(20) NOT NULL,\n    `lock_value`     VARCHAR(20) NOT NULL,\n    `expire`         BIGINT,\n    primary key (`lock_key`)\n    ) ENGINE = InnoDB\n    DEFAULT CHARSET = utf8mb4;\n\nINSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0);\nINSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);\nINSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);\nINSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);\n\n-- -------------- Create the database tables needed by the business in the example ----------------\nDROP TABLE IF EXISTS `storage_tbl`;\nCREATE TABLE `storage_tbl` (\n                               `id` int(11) NOT NULL AUTO_INCREMENT,\n                               `commodity_code` varchar(255) DEFAULT NULL,\n                               `count` int(11) DEFAULT 0,\n                               PRIMARY KEY (`id`),\n                               UNIQUE KEY (`commodity_code`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n\nDROP TABLE IF EXISTS `order_tbl`;\nCREATE TABLE `order_tbl` (\n                             `id` int(11) NOT NULL AUTO_INCREMENT,\n                             `user_id` varchar(255) DEFAULT NULL,\n                             `commodity_code` varchar(255) DEFAULT NULL,\n                             `count` int(11) DEFAULT 0,\n                             `money` int(11) DEFAULT 0,\n                             PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n\nDROP TABLE IF EXISTS `account_tbl`;\nCREATE TABLE `account_tbl` (\n                               `id` int(11) NOT NULL AUTO_INCREMENT,\n                               `user_id` varchar(255) DEFAULT NULL,\n                               `money` int(11) DEFAULT 0,\n                               PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/business-service/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <groupId>com.alibaba.cloud</groupId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    <artifactId>business-service</artifactId>\n    <name>Spring Cloud Starter Alibaba Seata Example - Business Service</name>\n    <packaging>jar</packaging>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-openfeign</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-loadbalancer</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-tx</artifactId>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/business-service/src/main/java/com/alibaba/cloud/examples/BusinessApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;\nimport org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;\nimport org.springframework.cloud.openfeign.EnableFeignClients;\nimport org.springframework.cloud.openfeign.FeignClient;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author xiaojing\n */\n@SpringBootApplication\n@EnableFeignClients\n@EnableDiscoveryClient(autoRegister = false)\n@LoadBalancerClients({\n\t\t@LoadBalancerClient(\"storage-service\"),\n\t\t@LoadBalancerClient(\"order-service\"),\n\t\t@LoadBalancerClient(\"service-provider\")\n})\npublic class BusinessApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(BusinessApplication.class, args);\n\t}\n\n\t@Bean\n\tpublic RestTemplate restTemplate() {\n\t\treturn new RestTemplate();\n\t}\n\n\t@FeignClient(\"storage-service\")\n\tpublic interface StorageService {\n\n\t\t@GetMapping(path = \"/storage/{commodityCode}/{count}\")\n\t\tString storage(@PathVariable(\"commodityCode\") String commodityCode,\n\t\t\t\t@PathVariable(\"count\") int count);\n\n\t}\n\n\t@FeignClient(\"order-service\")\n\tpublic interface OrderService {\n\n\t\t@PostMapping(path = \"/order\")\n\t\tString order(@RequestParam(\"userId\") String userId,\n\t\t\t\t@RequestParam(\"commodityCode\") String commodityCode,\n\t\t\t\t@RequestParam(\"orderCount\") int orderCount);\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/business-service/src/main/java/com/alibaba/cloud/examples/HomeController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport com.alibaba.cloud.examples.BusinessApplication.OrderService;\nimport com.alibaba.cloud.examples.BusinessApplication.StorageService;\nimport org.apache.seata.spring.annotation.GlobalTransactional;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.util.LinkedMultiValueMap;\nimport org.springframework.util.MultiValueMap;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author xiaojing\n */\n@RestController\npublic class HomeController {\n\n\tprivate static final Logger LOGGER = LoggerFactory.getLogger(HomeController.class);\n\n\tprivate static final String SUCCESS = \"SUCCESS\";\n\n\tprivate static final String FAIL = \"FAIL\";\n\n\tprivate static final String USER_ID = \"U100001\";\n\n\tprivate static final String COMMODITY_CODE = \"C00321\";\n\n\tprivate static final int ORDER_COUNT = 2;\n\n\tprivate final RestTemplate restTemplate;\n\n\tprivate final OrderService orderService;\n\n\tprivate final StorageService storageService;\n\n\tpublic HomeController(RestTemplate restTemplate, OrderService orderService,\n\t\t\tStorageService storageService) {\n\t\tthis.restTemplate = restTemplate;\n\t\tthis.orderService = orderService;\n\t\tthis.storageService = storageService;\n\t}\n\n\t@GlobalTransactional(timeoutMills = 300000, name = \"spring-cloud-demo-tx\")\n\t@GetMapping(value = \"/seata/rest\", produces = \"application/json\")\n\tpublic String rest() {\n\n\t\tString result = restTemplate.getForObject(\n\t\t\t\t\"http://127.0.0.1:18082/storage/\" + COMMODITY_CODE + \"/\" + ORDER_COUNT,\n\t\t\t\tString.class);\n\n\t\tif (!SUCCESS.equals(result)) {\n\t\t\tthrow new RuntimeException();\n\t\t}\n\n\t\tString url = \"http://127.0.0.1:18083/order\";\n\t\tHttpHeaders headers = new HttpHeaders();\n\t\theaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);\n\n\t\tMultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();\n\t\tmap.add(\"userId\", USER_ID);\n\t\tmap.add(\"commodityCode\", COMMODITY_CODE);\n\t\tmap.add(\"orderCount\", ORDER_COUNT + \"\");\n\n\t\tHttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(\n\t\t\t\tmap, headers);\n\n\t\tResponseEntity<String> response;\n\t\ttry {\n\t\t\tresponse = restTemplate.postForEntity(url, request, String.class);\n\t\t}\n\t\tcatch (Exception exx) {\n\t\t\tthrow new RuntimeException(\"mock error\");\n\t\t}\n\t\tresult = response.getBody();\n\t\tif (!SUCCESS.equals(result)) {\n\t\t\tthrow new RuntimeException();\n\t\t}\n\n\t\treturn SUCCESS;\n\t}\n\n\t@GlobalTransactional(timeoutMills = 300000, name = \"spring-cloud-demo-tx\")\n\t@GetMapping(value = \"/seata/feign\", produces = \"application/json\")\n\tpublic String feign() {\n\n\t\tString result = storageService.storage(COMMODITY_CODE, ORDER_COUNT);\n\n\t\tif (!SUCCESS.equals(result)) {\n\t\t\tthrow new RuntimeException();\n\t\t}\n\n\t\tresult = orderService.order(USER_ID, COMMODITY_CODE, ORDER_COUNT);\n\n\t\tif (!SUCCESS.equals(result)) {\n\t\t\tthrow new RuntimeException();\n\t\t}\n\n\t\treturn SUCCESS;\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/business-service/src/main/java/com/alibaba/cloud/examples/Order.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport java.io.Serializable;\n\npublic class Order implements Serializable {\n\n\t/**\n\t * order id.\n\t */\n\tpublic long id;\n\n\t/**\n\t * user id.\n\t */\n\tpublic String userId;\n\n\t/**\n\t * commodity code.\n\t */\n\tpublic String commodityCode;\n\n\t/**\n\t * count.\n\t */\n\tpublic int count;\n\n\t/**\n\t * money.\n\t */\n\tpublic int money;\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"Order{\" + \"id=\" + id + \", userId='\" + userId + '\\'' + \", commodityCode='\"\n\t\t\t\t+ commodityCode + '\\'' + \", count=\" + count + \", money=\" + money + '}';\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/business-service/src/main/resources/application.yml",
    "content": "server:\n  port: 18081\n\nspring:\n  cloud:\n    nacos:\n      discovery:\n        server-addr: 127.0.0.1:8848\n        username: 'nacos'\n        password: 'nacos'\n    loadbalancer:\n      ribbon:\n        enabled:true\n  application:\n    name: business-service\n\nseata:\n  enabled: true\n  application-id: ${spring.application.name}\n\n  tx-service-group: ${spring.application.name}-tx-group\n  config:\n    type: nacos\n    nacos:\n      serverAddr: 127.0.0.1:8848\n      dataId: \"seata.properties\"\n      group: SEATA_GROUP\n      username: 'nacos'\n      password: 'nacos'\n  registry:\n    type: nacos\n    nacos:\n      cluster: default\n      group: SEATA_GROUP\n      application: seata-server\n      server-addr: 127.0.0.1:8848\n      username: 'nacos'\n      password: 'nacos'\n\nfeign:\n  client:\n    config:\n      default:\n        connectTimeout: 10000\n        readTimeout: 10000\nlogging:\n  level:\n    io:\n      seata: debug\n\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/order-service/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <groupId>com.alibaba.cloud</groupId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    <artifactId>order-service</artifactId>\n    <name>Spring Cloud Starter Alibaba Seata Example - Order Service</name>\n    <packaging>jar</packaging>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-jdbc</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.mysql</groupId>\n            <artifactId>mysql-connector-j</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.apache.logging.log4j</groupId>\n            <artifactId>log4j-core</artifactId>\n        </dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/order-service/src/main/java/com/alibaba/cloud/examples/DatabaseConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport javax.sql.DataSource;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.jdbc.core.JdbcTemplate;\n\n/**\n * @author xiaojing\n */\n@Configuration\npublic class DatabaseConfiguration {\n\n//  druid don't support GraalVM now because of there is CGlib proxy\n//\t@Bean\n//\t@Primary\n//\t@ConfigurationProperties(\"spring.datasource\")\n//\tpublic DataSource storageDataSource() {\n//\t\treturn new DruidDataSource();\n//\t}\n\n\t@Bean\n\tpublic JdbcTemplate jdbcTemplate(DataSource dataSource) {\n\t\tJdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);\n\n\t\tjdbcTemplate.execute(\"TRUNCATE TABLE order_tbl\");\n\n\t\treturn jdbcTemplate;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/order-service/src/main/java/com/alibaba/cloud/examples/Order.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport java.io.Serializable;\n\npublic class Order implements Serializable {\n\n\t/**\n\t * id.\n\t */\n\tpublic long id;\n\n\t/**\n\t * user id.\n\t */\n\tpublic String userId;\n\n\t/**\n\t * commodity code.\n\t */\n\tpublic String commodityCode;\n\n\t/**\n\t * count.\n\t */\n\tpublic int count;\n\n\t/**\n\t * money.\n\t */\n\tpublic int money;\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"Order{\" + \"id=\" + id + \", userId='\" + userId + '\\'' + \", commodityCode='\"\n\t\t\t\t+ commodityCode + '\\'' + \", count=\" + count + \", money=\" + money + '}';\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/order-service/src/main/java/com/alibaba/cloud/examples/OrderApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author xiaojing\n */\n@SpringBootApplication\npublic class OrderApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(OrderApplication.class, args);\n\t}\n\n\t@Bean\n\tpublic RestTemplate restTemplate() {\n\t\treturn new RestTemplate();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/order-service/src/main/java/com/alibaba/cloud/examples/OrderController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.util.Random;\n\nimport org.apache.seata.core.context.RootContext;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.jdbc.core.PreparedStatementCreator;\nimport org.springframework.jdbc.support.GeneratedKeyHolder;\nimport org.springframework.jdbc.support.KeyHolder;\nimport org.springframework.util.LinkedMultiValueMap;\nimport org.springframework.util.MultiValueMap;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author xiaojing\n */\n@RestController\npublic class OrderController {\n\n\tprivate static final Logger LOGGER = LoggerFactory.getLogger(OrderController.class);\n\n\tprivate static final String SUCCESS = \"SUCCESS\";\n\n\tprivate static final String FAIL = \"FAIL\";\n\n\tprivate static final String USER_ID = \"U100001\";\n\n\tprivate static final String COMMODITY_CODE = \"C00321\";\n\n\tprivate final JdbcTemplate jdbcTemplate;\n\n\tprivate final RestTemplate restTemplate;\n\n\tprivate Random random;\n\n\tpublic OrderController(JdbcTemplate jdbcTemplate, RestTemplate restTemplate) {\n\t\tthis.jdbcTemplate = jdbcTemplate;\n\t\tthis.restTemplate = restTemplate;\n\t\tthis.random = new Random();\n\t}\n\n\t@PostMapping(value = \"/order\", produces = \"application/json\")\n\tpublic String order(String userId, String commodityCode, int orderCount) {\n\t\tLOGGER.info(\"Order Service Begin ... xid: \" + RootContext.getXID());\n\n\t\tint orderMoney = calculate(commodityCode, orderCount);\n\n\t\tinvokerAccountService(orderMoney);\n\n\t\tfinal Order order = new Order();\n\t\torder.userId = userId;\n\t\torder.commodityCode = commodityCode;\n\t\torder.count = orderCount;\n\t\torder.money = orderMoney;\n\n\t\tKeyHolder keyHolder = new GeneratedKeyHolder();\n\n\t\tint result = jdbcTemplate.update(new PreparedStatementCreator() {\n\n\t\t\t@Override\n\t\t\tpublic PreparedStatement createPreparedStatement(Connection con)\n\t\t\t\t\tthrows SQLException {\n\t\t\t\tPreparedStatement pst = con.prepareStatement(\n\t\t\t\t\t\t\"insert into order_tbl (user_id, commodity_code, count, money) values (?, ?, ?, ?)\",\n\t\t\t\t\t\tPreparedStatement.RETURN_GENERATED_KEYS);\n\t\t\t\tpst.setObject(1, order.userId);\n\t\t\t\tpst.setObject(2, order.commodityCode);\n\t\t\t\tpst.setObject(3, order.count);\n\t\t\t\tpst.setObject(4, order.money);\n\t\t\t\treturn pst;\n\t\t\t}\n\t\t}, keyHolder);\n\n\t\torder.id = keyHolder.getKey().longValue();\n\n\t\tif (random.nextBoolean()) {\n\t\t\tthrow new RuntimeException(\"this is a mock Exception\");\n\t\t}\n\n\t\tLOGGER.info(\"Order Service End ... Created \" + order);\n\n\t\tif (result == 1) {\n\t\t\treturn SUCCESS;\n\t\t}\n\t\treturn FAIL;\n\t}\n\n\tprivate int calculate(String commodityId, int orderCount) {\n\t\treturn 2 * orderCount;\n\t}\n\n\tprivate void invokerAccountService(int orderMoney) {\n\t\tString url = \"http://127.0.0.1:18084/account\";\n\t\tHttpHeaders headers = new HttpHeaders();\n\t\theaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);\n\n\t\tMultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();\n\n\t\tmap.add(\"userId\", USER_ID);\n\t\tmap.add(\"money\", orderMoney + \"\");\n\n\t\tHttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(\n\t\t\t\tmap, headers);\n\n\t\tResponseEntity<String> response = restTemplate.postForEntity(url, request,\n\t\t\t\tString.class);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/order-service/src/main/resources/application.yml",
    "content": "base:\n  config:\n    mdb:\n      hostname: 127.0.0.1 #your mysql server ip address\n      dbname: seata #your database name for test\n      port: 3306 #your mysql server listening port\n      username: 'root' #your mysql server username\n      password: 'root' #your mysql server password\nserver:\n  port: 18083\n\nspring:\n  cloud:\n    nacos:\n      discovery:\n        server-addr: 127.0.0.1:8848\n        username: 'nacos'\n        password: 'nacos'\n  application:\n    name: order-service\n  main:\n    allow-bean-definition-overriding: true\n  datasource:\n    name: storageDataSource\n#    druid don't support GraalVM now because of there is CGlib proxy\n#    type: com.alibaba.druid.pool.DruidDataSource\n    driver-class-name: com.mysql.cj.jdbc.Driver\n    url: jdbc:mysql://${base.config.mdb.hostname}:${base.config.mdb.port}/${base.config.mdb.dbname}?useSSL=false&serverTimezone=UTC\n    username: ${base.config.mdb.username}\n    password: ${base.config.mdb.password}\n#    druid:\n#      max-active: 20\n#      min-idle: 2\n#      initial-size: 2\n\nseata:\n  enabled: true\n  application-id: ${spring.application.name}\n  tx-service-group: ${spring.application.name}-tx-group\n  config:\n    type: nacos\n    nacos:\n      serverAddr: 127.0.0.1:8848\n      dataId: \"seata.properties\"\n      group: SEATA_GROUP\n      username: 'nacos'\n      password: 'nacos'\n  registry:\n    type: nacos\n    nacos:\n      cluster: default\n      group: SEATA_GROUP\n      application: seata-server\n      server-addr: 127.0.0.1:8848\n      username: 'nacos'\n      password: 'nacos'\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/readme-zh.md",
    "content": "# Seata Example\n\n## 项目说明\n\n本项目演示如何使用 Seata Starter 完成 Spring Cloud Alibaba 应用的分布式事务接入。\n\n[Seata](https://github.com/seata/seata) 是阿里巴巴开源的分布式事务中间件，以高效并且对业务 0 侵入的方式，解决微服务场景下面临的分布式事务问题。\n\n## 准备工作\n\n在运行此示例之前，需要完成以下几步准备工作：\n\n### 1. 配置数据库\n\n> **注意**： 实际上，Seata 支持不同的应用使用完全不相干的数据库，但是这里为了简单地演示 Seata 如何在 Spring Cloud 应用中使用，所以选择了 Mysql 数据库。\n\n将 `account-server`、`order-service`、`storage-service` 这三个应用中 resources 目录下的 `application.yml` 文件中的以下配置修改成本地环境中的数据库配置。\n\n```\nbase:\n  config:\n    mdb:\n      hostname: your mysql server ip address\n      dbname: your database name for test\n      port: your mysql server listening port\n      username: your mysql server username\n      password: your mysql server password\n```\n\n#### 创建 undo_log 表\n\nSeata AT 模式 需要使用到 undo_log 表。\n\n```sql\n-- 注意此处0.3.0+ 增加唯一索引 ux_undo_log\nCREATE TABLE `undo_log` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `branch_id` bigint(20) NOT NULL,\n  `xid` varchar(100) NOT NULL,\n  `context` varchar(128) NOT NULL,\n  `rollback_info` longblob NOT NULL,\n  `log_status` int(11) NOT NULL,\n  `log_created` datetime NOT NULL,\n  `log_modified` datetime NOT NULL,\n  `ext` varchar(100) DEFAULT NULL,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)\n) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;\n```\n\n#### 导入 seata-server db 模式所需要的数据库表\n在数据库中初始化[global_table、branch_table、lock_table、distributed_lock](https://github.com/seata/seata/blob/2.1.0/script/server/db/mysql.sql)\n\n```sql\n-- -------------------------------- The script used when storeMode is 'db' --------------------------------\n-- the table to store GlobalSession data\nCREATE TABLE IF NOT EXISTS `global_table`\n(\n    `xid`                       VARCHAR(128) NOT NULL,\n    `transaction_id`            BIGINT,\n    `status`                    TINYINT      NOT NULL,\n    `application_id`            VARCHAR(32),\n    `transaction_service_group` VARCHAR(32),\n    `transaction_name`          VARCHAR(128),\n    `timeout`                   INT,\n    `begin_time`                BIGINT,\n    `application_data`          VARCHAR(2000),\n    `gmt_create`                DATETIME,\n    `gmt_modified`              DATETIME,\n    PRIMARY KEY (`xid`),\n    KEY `idx_status_gmt_modified` (`status` , `gmt_modified`),\n    KEY `idx_transaction_id` (`transaction_id`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8mb4;\n\n-- the table to store BranchSession data\nCREATE TABLE IF NOT EXISTS `branch_table`\n(\n    `branch_id`         BIGINT       NOT NULL,\n    `xid`               VARCHAR(128) NOT NULL,\n    `transaction_id`    BIGINT,\n    `resource_group_id` VARCHAR(32),\n    `resource_id`       VARCHAR(256),\n    `branch_type`       VARCHAR(8),\n    `status`            TINYINT,\n    `client_id`         VARCHAR(64),\n    `application_data`  VARCHAR(2000),\n    `gmt_create`        DATETIME(6),\n    `gmt_modified`      DATETIME(6),\n    PRIMARY KEY (`branch_id`),\n    KEY `idx_xid` (`xid`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8mb4;\n\n-- the table to store lock data\nCREATE TABLE IF NOT EXISTS `lock_table`\n(\n    `row_key`        VARCHAR(128) NOT NULL,\n    `xid`            VARCHAR(128),\n    `transaction_id` BIGINT,\n    `branch_id`      BIGINT       NOT NULL,\n    `resource_id`    VARCHAR(256),\n    `table_name`     VARCHAR(32),\n    `pk`             VARCHAR(36),\n    `status`         TINYINT      NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',\n    `gmt_create`     DATETIME,\n    `gmt_modified`   DATETIME,\n    PRIMARY KEY (`row_key`),\n    KEY `idx_status` (`status`),\n    KEY `idx_branch_id` (`branch_id`),\n    KEY `idx_xid_and_branch_id` (`xid` , `branch_id`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8mb4;\n\nCREATE TABLE IF NOT EXISTS `distributed_lock`\n(\n    `lock_key`       CHAR(20) NOT NULL,\n    `lock_value`     VARCHAR(20) NOT NULL,\n    `expire`         BIGINT,\n    primary key (`lock_key`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8mb4;\n\nINSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0);\nINSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);\nINSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);\nINSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);\n```\n\n#### 创建应用示例中业务所需要的数据库表\n\n```sql\nDROP TABLE IF EXISTS `storage_tbl`;\nCREATE TABLE `storage_tbl` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `commodity_code` varchar(255) DEFAULT NULL,\n  `count` int(11) DEFAULT 0,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY (`commodity_code`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n\nDROP TABLE IF EXISTS `order_tbl`;\nCREATE TABLE `order_tbl` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `user_id` varchar(255) DEFAULT NULL,\n  `commodity_code` varchar(255) DEFAULT NULL,\n  `count` int(11) DEFAULT 0,\n  `money` int(11) DEFAULT 0,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n\nDROP TABLE IF EXISTS `account_tbl`;\nCREATE TABLE `account_tbl` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `user_id` varchar(255) DEFAULT NULL,\n  `money` int(11) DEFAULT 0,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n```\n\n### 2. 配置 Nacos\n\n> Spring Cloud Alibaba 适配了 Nacos 3.1.0 版本，在本示例中，使用 Nacos 3.1.0 作为 Seata 的配置中心组件。\n\n创建 Seata 的 Nacos 配置： data-id: `seata.properties` , Group: `SEATA_GROUP` (seata 2.x 默认分组) ,导入 [Seata Config](https://github.com/seata/seata/blob/2.1.0/script/config-center/config.txt)\n\n在 `seata.properties` 配置文件中增加应用示例中需要的以下配置项：[事务群组配置](https://seata.io/zh-cn/docs/user/configurations.html)\n\n```properties\n   service.vgroupMapping.default_tx_group=default  # 用于指定全局事务组和本地事务组之间的映射关系\n   service.vgroupMapping.order-service-tx-group=default\n   service.vgroupMapping.account-service-tx-group=default\n   service.vgroupMapping.business-service-tx-group=default\n   service.vgroupMapping.storage-service-tx-group=default\n```\n\n### 3. 启动 Seata-server\n\n> Seata 1.5.1 开始支持控制台 本地访问控制台地址：http://127.0.0.1:7091，通过 Seata 内置的控制台可以观察正在执行的事务信息和全局锁信息,事务执行结束即删除相关信息。\n\n#### 1. 下载\n\n点击下载( [Seata 2.5.0](https://github.com/apache/incubator-seata/releases/tag/v2.5.0)) 版本。 # github链接为源码包，需要使用 Maven 进行编译构建源码并生成 Seata 服务器 JAR 文件\n\n或点击下载( [Apache-seata-2.5.0-incubating-bin.tar.gz](https://seata.apache.org/zh-cn/download/seata-server))  #二进制包，方便配备seata-server进行调试\n\n#### 2. 配置 Seata-server\n\n修改 `seata-server\\conf\\application.yml` 配置文件中的以下配置项：\n\n- 注释 `group: SEATA_GROUP`\n- 添加 Nacos 用户名和密码\n\n```yml\nseata:\n  # nacos配置\n  config:\n    type: nacos \n    nacos:\n      server-addr:  #  Nacos 服务地址\n      # group: SEATA_GROUP\n      # namespace: public  # Nacos 命名空间（确保设置为实际值）\n      username: nacos\n      password: nacos\n      data-id: seata.properties  # Nacos 中的配置文件名\n      ##if use MSE Nacos with auth, mutex with username/password attribute\n      #access-key:\n      #secret-key:\n  registry:\n    # support: nacos 、 eureka 、 redis 、 zk  、 consul 、 etcd3 、 sofa 、 seata\n    type: nacos  # 使用 Nacos 作为注册中心\n    nacos:\n      application: seata-server\n      # group: SEATA_GROUP\n      # namespace: public  # Nacos 命名空间（确保设置为实际值）\n      cluster: default\n      server-addr:   # Nacos 注册中心地址\n      username: nacos\n      password: nacos\n```\n\n- 添加 store 及 server 设置（示例-非必要）\n\n```yml\n  store:\n    # 支持：file、db、redis、raft\n    mode: db  # 使用数据库模式\n    session:\n      mode: file\n    lock:\n      mode: file\n    db:\n      datasource: druid\n      db-type: mysql\n      driver-class-name: com.mysql.jdbc.Driver\n      url: jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true  # MySQL 数据库连接\n      user: root  # MySQL 用户名\n      password: rootpass  # MySQL 密码\n      min-conn: 10\n      max-conn: 100\n      global-table: global_table\n      branch-table: branch_table\n      lock-table: lock_table\n      distributed-lock-table: distributed_lock\n      vgroup-table: vgroup_table\n      query-limit: 1000\n      max-wait: 5000\n  server:\n    service-port: 8091  # 配置服务端口\n    max-commit-retry-timeout: -1\n    max-rollback-retry-timeout: -1\n    rollback-failed-unlock-enable: false\n    enable-check-auth: true\n    enable-parallel-request-handle: true\n    enable-parallel-handle-branch: false\n    retry-dead-threshold: 70000\n    xaer-nota-retry-timeout: 60000\n    enableParallelRequestHandle: true\n    applicationDataLimitCheck: true\n    applicationDataLimit: 64000\n    recovery:\n      committing-retry-period: 1000\n      async-committing-retry-period: 1000\n      rollbacking-retry-period: 1000\n      end-status-retry-period: 1000\n      timeout-retry-period: 1000\n    undo:\n      log-save-days: 7\n      log-delete-period: 86400000\n    session:\n      branch-async-queue-size: 5000  # 异步分支队列大小\n      enable-branch-async-remove: false  # 启用分支异步移除\n    ratelimit:\n      enable: false\n      bucketTokenNumPerSecond: 999999\n      bucketTokenMaxNum: 999999\n      bucketTokenInitialNum: 999999\n  metrics:\n    enabled: false\n    registry-type: compact\n    exporter-list: prometheus\n    exporter-prometheus-port: 9898\n  transport:\n    rpc-tc-request-timeout: 15000\n    enable-tc-server-batch-send-response: false\n    min-http-pool-size: 10\n    max-http-pool-size: 100\n    max-http-task-queue-size: 1000\n    http-pool-keep-alive-time: 500\n    shutdown:\n      wait: 3\n    thread-factory:\n      boss-thread-prefix: NettyBoss\n      worker-thread-prefix: NettyServerNIOWorker\n      boss-thread-size: 1\n```\n\n> **注意：**\n> Nacos 3.1.0 开启鉴权，需要配置 `username` 和 `password` 属性，否则登陆失败。更多 Nacos 3.1.0 版本相关配置，参考 `nacos-example`。\n> **Seata-server 启动时的 Nacos 服务注册分组需要和示例应用中的分组保持一致，否则出现无法找到 seata-server 的错误！**\n> 更多 Seata-server 以 Nacos 作为配置中心的配置请参考：https://seata.io/zh-cn/docs/ops/deploy-by-docker-compose/#nacos-db\n\n### 3. 启动 Seata-server\n\nWindows: \n\n```cmd\n./seata-server.bat\n```\n\nLinux/Mac\n\n```shell\nsh seata-server.sh\n```\n\n更多配置启动参数请参考：https://seata.io/zh-cn/docs/user/quickstart/#%E6%AD%A5%E9%AA%A4-4-%E5%90%AF%E5%8A%A8%E6%9C%8D%E5%8A%A1\n\n**注意** 如果你修改了 endpoint 且注册中心使用默认 file 类型，那么记得需要在各个示例工程中的 `file.conf` 文件中，修改 grouplist 的值(当 registry.conf 中 registry.type 或 config.type 为 file 时会读取内部的 file 节点中的文件名，若 type 不为 file 将直接从配置类型的对应元数据的注册配置中心读取数据)，推荐大家使用 nacos 作为配置注册中心。\n\n## 运行示例\n\n分别运行 `account-server`、`order-service`、`storage-service` 和 `business-service` 这三个应用的 Main 函数，启动示例。\n\n启动示例后，通过 HTTP 的 GET 方法访问如下 URL，可以分别验证在 `business-service` 中 通过 RestTemplate 和 FeignClient 调用其他服务的场景。\n\n```shell\nhttp://127.0.0.1:18081/seata/feign\n\nhttp://127.0.0.1:18081/seata/rest\n\n```\n\n调用服务接口时，可能出现两种返回\n\n1. SUCCESS：调用接口服务成功；\n2. 500 异常，business-service mock 异常。\n\n## 如何验证分布式事务成功？\n\n### Xid 信息是否成功传递\n\n在 `account-server`、`order-service` 和 `storage-service` 三个 服务的 Controller 中，第一个执行的逻辑都是输出 RootContext 中的 Xid 信息，如果看到都输出了正确的 Xid 信息，即每次都发生变化，且同一次调用中所有服务的 Xid 都一致。则表明 Seata 的 Xid 的传递和还原是正常的。\n\n```bash\n# 分别查看服务运行日志（示例）\nAccount Service ... xid: 192.168.44.1:8091:4540309594179612673\nOrder Service Begin ... xid: 192.168.44.1:8091:4540309594179612673\nStorage Service Begin ... xid: 192.168.44.1:8091:4540309594179612673\n...\nBegin new global transaction [192.168.44.1:8091:4540309594179612673]\n```\n\n### 数据库中数据是否一致\n\n在本示例中，我们模拟了一个用户购买货物的场景，StorageService 负责扣减库存数量，OrderService 负责保存订单，AccountService 负责扣减用户账户余额。\n\n为了演示样例，我们在 OrderService 和 AccountService 中 使用 Random.nextBoolean() 的方式来随机抛出异常,模拟了在服务调用时随机发生异常的场景。\n\n如果分布式事务生效的话， 那么以下等式应该成立\n\n\n- 用户原始金额(1000) = 用户现存的金额  +  货物单价 (2) * 订单数量 * 每单的货物数量(2)\n- 货物的初始数量(100) = 货物的现存数量 + 订单数量 * 每单的货物数量(2)\n\n```sql\n# 验证示例\nSELECT * FROM account_tbl;\nSELECT * FROM storage_tbl;\nSELECT * FROM order_tbl;\n```\n\n注：由于使用了 Random.nextBoolean() 来随机抛出异常，模拟事务的异常情况，也需要验证分布式事务是否能正确回滚：\n如果在 OrderService 和 AccountService 中抛出异常，StorageService 应该会回滚库存扣减，账户余额也应恢复到初始状态。\n查看分布式事务日志：查看 undo_log 表和 global_table 表，确保在事务回滚时，相关记录被删除或恢复。\n\n## 对 Spring Cloud 支持点\n\n- 通过 Spring MVC 提供服务的服务提供者，在收到 header 中含有 Seata 信息的 HTTP 请求时，可以自动还原 Seata 上下文。\n\n- 支持服务调用者通过 RestTemplate 调用时，自动传递 Seata 上下文。\n\n- 支持服务调用者通过 FeignClient 调用时，自动传递 Seata 上下文。\n\n- 支持 SeataClient 和 Hystrix 同时使用的场景。\n\n- 支持 SeataClient 和 Sentinel 同时使用的场景。\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/readme.md",
    "content": "# Seata Example\n\n## Project description\n\nThis project demonstrates how to use Seata Starter to complete the distributed transaction access of Spring Cloud Alibaba application.\n\n[Seata](https://github.com/seata/seata) It is Alibaba's open source distributed transaction middleware, which solves the distributed transaction problems faced by micro-service scenarios in an efficient and zero-intrusion way.\n\n## Preparations\n\nBefore you run this sample, you need to complete the following steps:\n\n### 1. Configure the database\n\n> Seata **Notice** actually supports disparate databases for different applications, but Mysql was chosen here for a simple demonstration of how Seata can be used in a Spring Cloud application.\n\nModify the following configuration in the files under the `application.yml` resources directory in the three applications `account-server`, `order-service`, `storage-service` to the database configuration in the local environment.\n\n```\nbase:\n  config:\n    mdb:\n      hostname: your mysql server ip address\n      dbname: your database name for test\n      port: your mysql server listening port\n      username: your mysql server username\n      password: your mysql server password\n```\n\n#### Create the undo _ log table\n\nSeata AT mode requires the undo_log table.\n\n```sql\n-- Note that 0.3.0+ adds unique index ux_undo_log here\nCREATE TABLE `undo_log` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `branch_id` bigint(20) NOT NULL,\n  `xid` varchar(100) NOT NULL,\n  `context` varchar(128) NOT NULL,\n  `rollback_info` longblob NOT NULL,\n  `log_status` int(11) NOT NULL,\n  `log_created` datetime NOT NULL,\n  `log_modified` datetime NOT NULL,\n  `ext` varchar(100) DEFAULT NULL,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)\n) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;\n```\n\n#### Import the database tables required by the seata-server db schema\nInitializing [global_table、branch_table、lock_table、distributed_lock](https://github.com/seata/seata/blob/2.1.0/script/server/db/mysql.sql) in the database\n\n```sql\n-- -------------------------------- The script used when storeMode is 'db' --------------------------------\n-- the table to store GlobalSession data\nCREATE TABLE IF NOT EXISTS `global_table`\n(\n    `xid`                       VARCHAR(128) NOT NULL,\n    `transaction_id`            BIGINT,\n    `status`                    TINYINT      NOT NULL,\n    `application_id`            VARCHAR(32),\n    `transaction_service_group` VARCHAR(32),\n    `transaction_name`          VARCHAR(128),\n    `timeout`                   INT,\n    `begin_time`                BIGINT,\n    `application_data`          VARCHAR(2000),\n    `gmt_create`                DATETIME,\n    `gmt_modified`              DATETIME,\n    PRIMARY KEY (`xid`),\n    KEY `idx_status_gmt_modified` (`status` , `gmt_modified`),\n    KEY `idx_transaction_id` (`transaction_id`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8mb4;\n\n-- the table to store BranchSession data\nCREATE TABLE IF NOT EXISTS `branch_table`\n(\n    `branch_id`         BIGINT       NOT NULL,\n    `xid`               VARCHAR(128) NOT NULL,\n    `transaction_id`    BIGINT,\n    `resource_group_id` VARCHAR(32),\n    `resource_id`       VARCHAR(256),\n    `branch_type`       VARCHAR(8),\n    `status`            TINYINT,\n    `client_id`         VARCHAR(64),\n    `application_data`  VARCHAR(2000),\n    `gmt_create`        DATETIME(6),\n    `gmt_modified`      DATETIME(6),\n    PRIMARY KEY (`branch_id`),\n    KEY `idx_xid` (`xid`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8mb4;\n\n-- the table to store lock data\nCREATE TABLE IF NOT EXISTS `lock_table`\n(\n    `row_key`        VARCHAR(128) NOT NULL,\n    `xid`            VARCHAR(128),\n    `transaction_id` BIGINT,\n    `branch_id`      BIGINT       NOT NULL,\n    `resource_id`    VARCHAR(256),\n    `table_name`     VARCHAR(32),\n    `pk`             VARCHAR(36),\n    `status`         TINYINT      NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',\n    `gmt_create`     DATETIME,\n    `gmt_modified`   DATETIME,\n    PRIMARY KEY (`row_key`),\n    KEY `idx_status` (`status`),\n    KEY `idx_branch_id` (`branch_id`),\n    KEY `idx_xid_and_branch_id` (`xid` , `branch_id`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8mb4;\n\nCREATE TABLE IF NOT EXISTS `distributed_lock`\n(\n    `lock_key`       CHAR(20) NOT NULL,\n    `lock_value`     VARCHAR(20) NOT NULL,\n    `expire`         BIGINT,\n    primary key (`lock_key`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8mb4;\n\nINSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0);\nINSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);\nINSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);\nINSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);\n```\n\n#### Create the database tables required by the business in the application sample\n\n```sql\nDROP TABLE IF EXISTS `storage_tbl`;\nCREATE TABLE `storage_tbl` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `commodity_code` varchar(255) DEFAULT NULL,\n  `count` int(11) DEFAULT 0,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY (`commodity_code`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n\nDROP TABLE IF EXISTS `order_tbl`;\nCREATE TABLE `order_tbl` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `user_id` varchar(255) DEFAULT NULL,\n  `commodity_code` varchar(255) DEFAULT NULL,\n  `count` int(11) DEFAULT 0,\n  `money` int(11) DEFAULT 0,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n\nDROP TABLE IF EXISTS `account_tbl`;\nCREATE TABLE `account_tbl` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `user_id` varchar(255) DEFAULT NULL,\n  `money` int(11) DEFAULT 0,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n```\n\n### 2. Configure Nacos\n\n> Spring Cloud Alibaba is adapted with Nacos 3.1.0. In this example, Nacos 3.1.0 is used as the configuration center component of Seata.\n\nCreate Nacos configuration for Seata: data-id: `seata.properties`, Group: `SEATA_GROUP` (default grouping for seata 2.1.0), import\n\nAdd the following configuration items required in the application example to the `seata.properties` configuration file: [事务群组配置](https://seata.io/zh-cn/docs/user/configurations.html)\n\n```properties\n   service.vgroupMapping.default_tx_group=default  # Used to specify the mapping relationship between global transaction groups and local transaction groups.\n   service.vgroupMapping.order-service-tx-group=default\n   service.vgroupMapping.account-service-tx-group=default\n   service.vgroupMapping.business-service-tx-group=default\n   service.vgroupMapping.storage-service-tx-group=default\n```\n\n### 3. Start Seata-server\n\n> Seata 1.5.1 supports console local access. Console address: http://127.0.0.1:7091, you can view the information about the transaction being executed and the global lock information through the built-in console of Seata. When the transaction is finished, the relevant information will be deleted.\n\n#### 1. Download\n\nClick Download [Seata 2.5.0](https://github.com/apache/incubator-seata/releases/tag/v2.5.0) Version. \\# The GitHub link is for the source code package, which requires Maven to compile and build the source code and generate the Seata server JAR file.\n\nOr click Download [Apache-seata-2.5.0-incubating-bin.tar.gz](https://seata.apache.org/zh-cn/download/seata-server) .  \\# Binary package, convenient for debugging with seata-server\n\n#### 2. Configure Seata-server\n\nModify `seata-server\\conf\\application.yml` the following configuration items in the configuration file:\n\n- Comment `group: SEATA_GROUP`\n- Add Nacos username and password\n\n```yml\nseata:\n  # nacos configuration\n  config:\n    type: nacos \n    nacos:\n      server-addr:  #  Nacos service addr\n      # group: SEATA_GROUP\n      # namespace: public  # Nacos Namespace\n      username: nacos\n      password: nacos\n      data-id: seata.properties  # Configuration file name in Nacos\n      ##if use MSE Nacos with auth, mutex with username/password attribute\n      #access-key:\n      #secret-key:\n  registry:\n    # support: nacos 、 eureka 、 redis 、 zk  、 consul 、 etcd3 、 sofa 、 seata\n    type: nacos  # Using Nacos as a registry center\n    nacos:\n      application: seata-server\n      # group: SEATA_GROUP\n      # namespace: public  # Nacos namespace (make sure to set it to the actual value)\n      cluster: default\n      server-addr:   # Nacos registry center address\n      username: nacos\n      password: nacos\n```\n\n- Add store and server settings (example - not required)\n\n```yml\n  store:\n    # Support: file, db, redis, raft\n    mode: db  # Using database models\n    session:\n      mode: file\n    lock:\n      mode: file\n    db:\n      datasource: druid\n      db-type: mysql\n      driver-class-name: com.mysql.jdbc.Driver\n      url: jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true  # MySQL database connection\n      user: root  # MySQL username\n      password: rootpass  # MySQL password\n      min-conn: 10\n      max-conn: 100\n      global-table: global_table\n      branch-table: branch_table\n      lock-table: lock_table\n      distributed-lock-table: distributed_lock\n      vgroup-table: vgroup_table\n      query-limit: 1000\n      max-wait: 5000\n  server:\n    service-port: 8091  # Configure service port\n    max-commit-retry-timeout: -1\n    max-rollback-retry-timeout: -1\n    rollback-failed-unlock-enable: false\n    enable-check-auth: true\n    enable-parallel-request-handle: true\n    enable-parallel-handle-branch: false\n    retry-dead-threshold: 70000\n    xaer-nota-retry-timeout: 60000\n    enableParallelRequestHandle: true\n    applicationDataLimitCheck: true\n    applicationDataLimit: 64000\n    recovery:\n      committing-retry-period: 1000\n      async-committing-retry-period: 1000\n      rollbacking-retry-period: 1000\n      end-status-retry-period: 1000\n      timeout-retry-period: 1000\n    undo:\n      log-save-days: 7\n      log-delete-period: 86400000\n    session:\n      branch-async-queue-size: 5000  # Asynchronous branch queue size\n      enable-branch-async-remove: false  # Enable branch asynchronous removal\n    ratelimit:\n      enable: false\n      bucketTokenNumPerSecond: 999999\n      bucketTokenMaxNum: 999999\n      bucketTokenInitialNum: 999999\n  metrics:\n    enabled: false\n    registry-type: compact\n    exporter-list: prometheus\n    exporter-prometheus-port: 9898\n  transport:\n    rpc-tc-request-timeout: 15000\n    enable-tc-server-batch-send-response: false\n    min-http-pool-size: 10\n    max-http-pool-size: 100\n    max-http-task-queue-size: 1000\n    http-pool-keep-alive-time: 500\n    shutdown:\n      wait: 3\n    thread-factory:\n      boss-thread-prefix: NettyBoss\n      worker-thread-prefix: NettyServerNIOWorker\n      boss-thread-size: 1\n```\n\n> **Notice**\n> Nacos 3.1.0 enables authentication. Configuration `username` and `password` properties are required, otherwise login fails. For more Nacos 3.1.0 related configurations, refer to `nacos-example`.\n> **The Nacos service registration group when seata-server is started must be consistent with the group in the sample application, otherwise an error that seata-server cannot be found will occur!**\n> For more information about the configuration of Seata-server with Nacos as the configuration center, please refer to https://seata.io/zh-cn/docs/ops/deploy-by-docker-compose/#nacos-db.\n\n### 3. Start Seata-server\n\nWindows:\n\n```cmd\n./seata-server.bat\n```\n\nLinux/Mac\n\n```shell\nsh seata-server.sh\n```\n\nFor more configuration startup parameters, please refer to https://seata.io/zh-cn/docs/user/quickstart/#%E6%AD%A5%E9%AA%A4-4-%E5%90%AF%E5%8A%A8%E6%9C%8D%E5%8A%A1.\n\n**Notice** If you change the endpoint and the registry uses the default file type, remember that in the `file.conf` file in each sample project, Modify the value of grouplist (when the registry. Type or config. Type in the registry. Conf is file, the file name in the internal file node will be read. If the type is not file, the data will be directly read from the registration configuration center of the corresponding metadata of the configuration type. It is recommended to use nacos as the configuration registration center.\n\n## Run the sample\n\nStart the sample by running `account-server` the Main functions of the, `order-service`, `storage-service`, and `business-service` applications separately.\n\nAfter starting the sample, access the following URL through the GET method of HTTP to verify `business-service` the scenarios of calling other services through RestTemplate and FeignClient in respectively.\n\n```shell\nhttp://127.0.0.1:18081/seata/feign\n\nhttp://127.0.0.1:18081/seata/rest\n```\n\nWhen a service interface is invoked, two types of returns are possible\n\n1. SUCCESS: calling interface service succeeded;\n2. 500 exception, business-service mock exception.\n\n## How do I verify that a distributed transaction is successful?\n\n### Xid information passed successfully\n\nIn `account-server` the Controllers of, `order-service`, and `storage-service` services, the first logic to be executed is to output the Xid information in the RootContext. If the correct Xid information is output, that is, it changes every time. And that Xid of all the services in the same invocation are the same. Then it indicates that the passing and restoring of Seata's Xid is normal.\n\n```bash\n# View service operation logs separately (example)\nAccount Service ... xid: 192.168.44.1:8091:4540309594179612673\nOrder Service Begin ... xid: 192.168.44.1:8091:4540309594179612673\nStorage Service Begin ... xid: 192.168.44.1:8091:4540309594179612673\n...\nBegin new global transaction [192.168.44.1:8091:4540309594179612673]\n```\n\n### Whether the data in the database is consistent\n\nIn this example, we simulate a scenario in which a user purchases goods. The Storage Service is responsible for deducting the inventory quantity, the Order Service is responsible for saving the order, and the Account service is responsible for deducting the balance of the user's account.\n\nTo demonstrate the sample, we use Random. NextBoolean () to randomly throw exceptions in Order Service and AccountService, simulating a scenario where exceptions randomly occur during service invocation.\n\nIf a distributed transaction is in effect, then the following equation should hold\n\n- User's original amount (1000) = user's existing amount + unit price of goods (2) *Number of orders* quantity of goods per order (2)\n- Initial quantity of goods (100) = Quantity on hand of goods + Order quantity * Quantity of goods per order (2)\n\n```sql\n# Verification example\nSELECT * FROM account_tbl;\nSELECT * FROM storage_tbl;\nSELECT * FROM order_tbl;\n```\n\nNote: Since Random.nextBoolean() is used to randomly throw exceptions to simulate transaction exceptions, it is also necessary to verify whether distributed transactions can be rolled back correctly:  \n\nIf exceptions are thrown in OrderService and AccountService, StorageService should roll back the inventory deduction, and the account balance should also be restored to its initial state.\n\nView the distributed transaction logs: Check the undo_log table and global_table table to ensure that relevant records are deleted or restored during transaction rollback.\n\n## Support points for Spring Cloud\n\n- Service providers that provide services through Spring MVC can automatically restore the Seata context when they receive an HTTP request with Seata information in the header.\n\n- Support the automatic passing of the Seata context when the service caller invokes through the RestTemplate.\n\n- Support the automatic passing of the Seata context when the service caller calls through FeignClient.\n\n- Scenarios where SeataClient and Hystrix are used together are supported.\n\n- Scenarios where SeataClient and Sentinel are used together are supported.\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/storage-service/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <groupId>com.alibaba.cloud</groupId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    <artifactId>storage-service</artifactId>\n    <name>Spring Cloud Starter Alibaba Seata Example - Storage Service</name>\n    <packaging>jar</packaging>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-jdbc</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.mysql</groupId>\n            <artifactId>mysql-connector-j</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.apache.logging.log4j</groupId>\n            <artifactId>log4j-core</artifactId>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/StorageApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * @author xiaojing\n */\n@SpringBootApplication\npublic class StorageApplication {\n\n\tpublic static void main(String[] args) {\n\n\t\tSpringApplication.run(StorageApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/config/DatabaseConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.config;\n\nimport javax.sql.DataSource;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.jdbc.core.JdbcTemplate;\n\n/**\n * @author xiaojing\n */\n@Configuration\npublic class DatabaseConfiguration {\n\n\n//  druid don't support GraalVM now because of there is CGlib proxy\n\t/*@Bean\n\t@Primary\n\t@ConfigurationProperties(\"spring.datasource\")\n\tpublic DataSource storageDataSource() {\n\t\treturn new DruidDataSource();\n\t}*/\n\n\t@Bean\n\tpublic JdbcTemplate jdbcTemplate(DataSource dataSource) {\n\n\t\tJdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);\n\n\t\tjdbcTemplate.update(\"delete from storage_tbl where commodity_code = 'C00321'\");\n\t\tjdbcTemplate.update(\n\t\t\t\t\"insert into storage_tbl(commodity_code, count) values ('C00321', 100)\");\n\n\t\treturn jdbcTemplate;\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/controller/StorageController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.controller;\n\nimport org.apache.seata.core.context.RootContext;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author xiaojing\n */\n@RestController\npublic class StorageController {\n\n\tprivate static final Logger LOGGER = LoggerFactory.getLogger(StorageController.class);\n\n\tprivate static final String SUCCESS = \"SUCCESS\";\n\n\tprivate static final String FAIL = \"FAIL\";\n\n\tprivate final JdbcTemplate jdbcTemplate;\n\n\tpublic StorageController(JdbcTemplate jdbcTemplate) {\n\t\tthis.jdbcTemplate = jdbcTemplate;\n\t}\n\n\t@GetMapping(value = \"/storage/{commodityCode}/{count}\", produces = \"application/json\")\n\tpublic String echo(@PathVariable String commodityCode, @PathVariable int count) {\n\t\tLOGGER.info(\"Storage Service Begin ... xid: \" + RootContext.getXID());\n\t\tint result = jdbcTemplate.update(\n\t\t\t\t\"update storage_tbl set count = count - ? where commodity_code = ?\",\n\t\t\t\tnew Object[] { count, commodityCode });\n\t\tLOGGER.info(\"Storage Service End ... \");\n\t\tif (result == 1) {\n\t\t\treturn SUCCESS;\n\t\t}\n\t\treturn FAIL;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/seata-example/storage-service/src/main/resources/application.yml",
    "content": "base:\n  config:\n    mdb:\n      hostname: 127.0.0.1 #your mysql server ip address\n      dbname: seata #your database name for test\n      port: 3306 #your mysql server listening port\n      username: 'root' #your mysql server username\n      password: 'root' #your mysql server password\n\nserver:\n  port: 18082\n\nspring:\n  cloud:\n    nacos:\n      discovery:\n        server-addr: 127.0.0.1:8848\n        username: 'nacos'\n        password: 'nacos'\n  application:\n    name: storage-service\n  main:\n    allow-bean-definition-overriding: true\n  datasource:\n    name: storageDataSource\n#    druid don't support GraalVM now because of there is CGlib proxy\n#    type: com.alibaba.druid.pool.DruidDataSource\n    driver-class-name: com.mysql.cj.jdbc.Driver\n    url: jdbc:mysql://${base.config.mdb.hostname}:${base.config.mdb.port}/${base.config.mdb.dbname}?useSSL=false&serverTimezone=UTC\n    username: ${base.config.mdb.username}\n    password: ${base.config.mdb.password}\n#    druid:\n#      max-active: 20\n#      min-idle: 2\n#      initial-size: 2\n\nseata:\n  enabled: true\n  application-id: ${spring.application.name}\n  tx-service-group: ${spring.application.name}-tx-group\n  config:\n    type: nacos\n    nacos:\n      serverAddr: 127.0.0.1:8848\n      dataId: \"seata.properties\"\n      group: SEATA_GROUP\n      username: 'nacos'\n      password: 'nacos'\n  registry:\n    type: nacos\n    nacos:\n      cluster: default\n      group: SEATA_GROUP\n      application: seata-server\n      server-addr: 127.0.0.1:8848\n      username: 'nacos'\n      password: 'nacos'\n\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/README-zh.md",
    "content": "# Spring Cloud Alibaba Sentinel Example\n\n## 项目说明\n\n本 Example 项目演示如何使用 `spring-cloud-starter-alibaba-sentinel` 完成 Spring Cloud 应用中的流量治理功能。\n\n[Sentinel](https://github.com/alibaba/Sentinel) 是阿里巴巴开源的分布式系统的流量防卫组件，Sentinel 以流量作为切入点，从流量控制，熔断降级，系统负载保护等多个维度保护服务的稳定性。\n\n## Sentinel Example \n\n在本 Example 项目中，主要演示 Sentinel 断路器，整合 Spring Cloud Gateway 和 OpenFeign、RestTemplate 以及 Webclient 的使用。\n\n### 下载并启动 Sentinel Console\n\n1. 首先需要获取 Sentinel 控制台，Sentinel Console 支持直接下载和源码构建两种方式\n\n   1. 直接下载：[下载 Sentinel 控制台](https://github.com/alibaba/Sentinel/releases)\n   2. 源码构建：进入 Sentinel [Github 项目页面](https://github.com/alibaba/Sentinel)，将代码 clone 到本地自行编译打包，[参考此文档](https://github.com/alibaba/Sentinel/blob/1.8/sentinel-dashboard/README.md)。\n      \n\n2. 启动控制台，执行 Java 命令 `java -jar sentinel-dashboard.jar` 完成 Sentinel 控制台的启动。\n\n   控制台默认的监听端口为 `8080`。Sentinel 控制台使用 Spring Boot 编程模型开发，如果需要指定其他端口，请使用 Spring Boot 容器配置的标准方式，详情请参考 [Spring Boot 文档](https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-customizing-embedded-containers)。\n\n### Sentinel Core Example\n\n在此 Example 模块中，主要演示如何使用 Sentinel 的基本功能完成 Spring Cloud 应用的流量管控。 在启动 Example 进行演示之前，先了解一下如何在 Spring Cloud 应用中接入 Sentinel 组件。\n\n#### 项目编写\n\n> **注意：本文档只是为了便于理解接入方式。本示例代码中已经完成接入工作，您无需再进行修改。**\n\n1. 首先，修改 `pom.xml` 文件，引入 Sentinel starter。\n\n   ```xml\n   <dependency>\n       <groupId>com.alibaba.cloud</groupId>\n       <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>\n   </dependency>\n   ```\n\n2. 接入限流埋点\n\n    - HTTP 埋点\n      `spring-cloud-starter-alibaba-sentinel` 默认为所有的 HTTP 服务提供了限流埋点，如果只想对 HTTP 服务进行限流，那么只需要引入依赖，无需修改代码。\n\n    - 自定义埋点\n      如果需要对某个特定的方法进行限流或降级，可以通过 `@SentinelResource` 注解来完成限流的埋点，示例代码如下：\n\n      ```java\n      @SentinelResource(\"resource\")\n      public String hello() {\n          return \"Hello\";\n      }\n      ```\n\n    当然也可以通过原始的 `SphU.entry(xxx)` 方法进行埋点，可以参见 [Sentinel 文档](https://github.com/alibaba/Sentinel/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8#%E5%AE%9A%E4%B9%89%E8%B5%84%E6%BA%90)。\n\n3. 配置限流规则\n\n   Sentinel 提供了两种配置限流规则的方式：代码配置 和 控制台配置。本示例使用的方式为通过代码配置。\n\n    1. 通过代码来实现限流规则的配置。一个简单的限流规则配置示例代码如下，更多限流规则配置详情请参考 [Sentinel 文档](https://github.com/alibaba/Sentinel/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8#%E5%AE%9A%E4%B9%89%E8%A7%84%E5%88%99)。\n\n       ```java\n       List<FlowRule> rules = new ArrayList<FlowRule>();\n       FlowRule rule = new FlowRule();\n       rule.setResource(str);\n       // set limit qps to 10\n       rule.setCount(10);\n       rule.setGrade(RuleConstant.FLOW_GRADE_QPS);\n       rule.setLimitApp(\"default\");\n       rules.add(rule);\n       FlowRuleManager.loadRules(rules);\n       ```\n\n    2. 通过控制台进行限流规则配置请参考文章后面的图文说明。\n\n#### 应用启动\n\n1. 增加配置，在应用的 `/src/main/resources/application.yml` 中添加基本配置信息\n\n    ```yaml\n    server:\n      port: 18083\n      \n    spring:\n      application:\n        name: sentinel-core-example\n    \n      cloud:\n        sentinel:\n          transport:\n            dashboard: localhost:8080\n    ```\n\n2. 启动应用，支持 IDE 直接启动和编译打包后启动。\n\n    1. IDE直接启动：找到主类 `SentinelCoreApplication`，执行 main 方法启动应用。\n    2. 打包编译后启动：首先执行 `mvn clean package` 将工程编译打包，然后执行 `java -jar sentinel-core-example.jar` 启动应用。\n\n#### 调用服务验证\n\n使用 curl 命令分别调用两个 URL，可以看到访问成功。\n\n```shell\n$ curl http://localhost:18083/test\nBlocked by Sentinel (flow limiting)\n\n$ curl http://localhost:18083/hello\nHello\n```\n\n#### 配置限流规则并验证\n\n1. 访问 http://localhost:8080 页面，进行登陆，默认用户名和密码均为：`sentinel`。\n\n   可以在左侧看到 `sentinel-core-example` 应用已经注册到了控制台，单击 **流控规则** ，可以看到目前的流控规则为空。\n\n   > **注意：如果您在控制台没有找到应用，请调用一下进行了 Sentinel 埋点的 URL 或方法，因为 Sentinel 使用了 lazy load 策略。详细的排查过程请参见 [Sentinel FAQ](https://github.com/alibaba/Sentinel/wiki/FAQ)。**\n\n<img src=\"./images/image-20240428171413303.png\" alt=\"image-20240428171413303\" style=\"zoom:50%;\" />\n\n2. 配置 URL 限流规则：点击新增流控规则，资源名填写需要限流的 URL 相对路径，单机阈值选择需要限流的阈值，点击新增进行确认。(为了便于演示效果，这里将值设置成了 1)。\n\n<img src=\"./images/image-20240428171245517.png\" alt=\"image-20240428171245517\" style=\"zoom: 50%;\" />\n\n3. 配置自定义限流规则：点击新增流控规则，资源名填写 `@SentinelResource` 注解 `value` 字段的值，单机阈值选择需要限流的阈值，点击新增进行确认。(为了便于演示效果，这里将值设置成了 1)。\n\n<img src=\"./images/image-20240428171608519.png\" alt=\"image-20240428171608519\" style=\"zoom:50%;\" />\n\n4. 访问 URL，当 QPS 超过 1 时,可以看到限流效果如下。\n\n   ![image-20240428171907705](./images/image-20240428171907705.png)\n\n#### 自定义限流处理逻辑\n\n* 默认限流异常处理\n\n  URL 限流触发后默认处理逻辑是，直接返回 \"Blocked by Sentinel (flow limiting)\"。 如果需要自定义处理逻辑，实现的方式如下：\n\n  ```java\n  public class CustomUrlBlockHandler implements UrlBlockHandler {\n      @Override\n      public void blocked(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException {\n          // todo add your logic\n      }\n  }\n  \n  WebCallbackManager.setUrlBlockHandler(new CustomUrlBlockHandler());\n  ```\n\n* 使用 `@SentinelResource` 注解下的限流异常处理\n\n  如果需要自定义处理逻辑，填写 `@SentinelResource` 注解的 `blockHandler` 属性（针对所有类型的 `BlockException`，需自行判断）或 `fallback` 属性（针对熔断降级异常），注意**对应方法的签名和位置有限制**，详情见 [Sentinel 注解支持文档](https://github.com/alibaba/Sentinel/wiki/%E6%B3%A8%E8%A7%A3%E6%94%AF%E6%8C%81#sentinelresource-%E6%B3%A8%E8%A7%A3)。示例实现如下：\n\n  ```java\n  public class TestService {\n  \n      // blockHandler 是位于 ExceptionUtil 类下的 handleException 静态方法，需符合对应的类型限制.\n      @SentinelResource(value = \"test\", blockHandler = \"handleException\", blockHandlerClass = {ExceptionUtil.class})\n      public void test() {\n          System.out.println(\"Test\");\n      }\n  \n      // blockHandler 是位于当前类下的 exceptionHandler 方法，需符合对应的类型限制.\n      @SentinelResource(value = \"hello\", blockHandler = \"exceptionHandler\")\n      public String hello(long s) {\n          return String.format(\"Hello at %d\", s);\n      }\n  \n      public String exceptionHandler(long s, BlockException ex) {\n          // Do some log here.\n          ex.printStackTrace();\n          return \"Oops, error occurred at \" + s;\n      }\n  }\n  \n  public final class ExceptionUtil {\n  \n      public static void handleException(BlockException ex) {\n          System.out.println(\"Oops: \" + ex.getClass().getCanonicalName());\n      }\n  }\n  ```\n\n一个简单的 `@SentinelResource` 示例可以见 [sentinel-demo-annotation-spring-aop](https://github.com/alibaba/Sentinel/tree/2021.x/sentinel-demo/sentinel-demo-annotation-spring-aop)。\n\n### Sentinel Circuitbreaker Example\n\n本 Example 主要演示 OpenFeign 整合 Sentinel 断路器的使用。\n\n#### 准备配置文件\n\n1. 添加配置到配置中心。dataId 为 `sentinel-circuitbreaker-rules.yml`\n\n   ```yml\n   feign:\n     circuitbreaker:\n       enabled: true # 开启 feign 断路器支持\n     sentinel:\n       default-rule: default # 默认规则名称\n       rules:\n         # 默认规则, 对所有 feign client 生效\n         default:\n           - grade: 2 # 根据异常数目降级\n             count: 1\n             timeWindow: 15 # 降级后到半开状态的时间\n             statIntervalMs: 1000\n             minRequestAmount: 1\n         # 只对 feign client user 生效\n         user:\n           - grade: 2\n             count: 1\n             timeWindow: 15\n             statIntervalMs: 1000\n             minRequestAmount: 1\n         # 只对 feign client user 的方法 feignMethod 生效\n         # 括号里是参数类型, 多个逗号分割, 比如 user#method(boolean,String,Map)\n         \"[user#feignMethod(boolean)]\":\n           - grade: 2\n             count: 1\n             timeWindow: 10\n             statIntervalMs: 1000\n             minRequestAmount: 1\n   ```\n\n#### 验证配置生效\n\n启动项目主类 `FeignCircuitBreakerApplication`\n\n##### 验证默认 Feign client 生效\n\n先访问 http://localhost/test/default/false 2 次 （1秒内）  \n再访问 http://localhost/test/default/true 断路器处于打开状态\n\n##### 验证指定 Feign client 生效\n\n先访问 http://localhost/test/feign/false 2 次 （1秒内）  \n再访问 http://localhost/test/feign/true 断路器处于打开状态\n\n##### 验证 Feign client 指定方法生效\n\n先访问 http://localhost/test/feignMethod/false 2次 （1秒内）  \n再访问 http://localhost/test/feignMethod/true 断路器处于打开状态\n\n#### 规则动态刷新\n\n修改配置中心的规则, 再访问上述接口。\n\n### Sentinel OpenFeign Example\n\n本 Example  演示 OpenFeing 与 Sentinel 的整合。Example 中使用 httpbin 充当后台 API 接口服务。\n\n#### 项目编写\n\n> **注意：本项目中代码已经完成相对应的功能，不需要再进行任何修改。**\n\n项目支持两种启动方式：通过主类 `OpenFeignApplication` 启动和 Jar 包启动两种方式。\n\n#### 调用测试\n\n项目启动完成之后，可以通过访问对应的 URL 访问，查看对应的 Sentinel 流控效果。\n\n> **注意：项目中提供的 RestTemplate 和 Webclient Example 同理。**\n\n## Endpoint 信息查看\n\nSpring Boot 应用支持通过 Endpoint 来暴露相关信息，`spring-cloud-starter-alibaba-sentinel` 也支持这一点。\n\n在使用之前需要在 Maven 中添加 `spring-boot-starter-actuator`依赖，并在配置中允许 Endpoints 的访问。\n* Spring Boot 1.x 中添加配置 `management.security.enabled=false`\n* Spring Boot 2.x 中添加配置 `management.endpoints.web.exposure.include=*`\n\nSpring Boot 1.x 可以通过访问 http://127.0.0.1:18083/sentinel 来查看 Sentinel Endpoint 的信息。Spring Boot 2.x 可以通过访问 http://127.0.0.1:18083/actuator/sentinel 来访问。\n\n<p align=\"center\"><img src=\"https://cdn.yuque.com/lark/0/2018/png/54319/1532084199224-1a41591d-7a06-4680-be8a-5de319ac635d.png\" width=\"480\" heigh='360' ></p>\n\n## 查看实时监控\nSentinel 控制台支持实时监控查看，您可以通过 Sentinel 控制台查看各链路的请求的通过数和被限流数等信息。\n其中 `p_qps` 为通过(pass) 流控的 QPS，`b_qps` 为被限流 (block) 的 QPS。\n\n<p align=\"center\"><img src=\"https://cdn.nlark.com/lark/0/2018/png/54319/1532313595369-8428cd7d-9eb7-4786-a149-acf0da4a2daf.png\" width=\"480\" heigh='180' ></p>\n\n## ReadableDataSource 支持\n\nSentinel 内部提供了[动态规则的扩展实现 ReadableDataSource](https://github.com/alibaba/Sentinel/wiki/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%99%E6%89%A9%E5%B1%95#datasource-%E6%89%A9%E5%B1%95)。\n\nSentinel starter 整合了目前存在的几类 ReadableDataSource。只需要在配置文件中进行相关配置，即可在 Spring 容器中自动注册 DataSource。\n\n比如要定义两个ReadableDataSource，分别是 `FileRefreshableDataSource` 和 `NacosDataSource`，配置如下：\n\n```properties\nspring.cloud.sentinel.datasource.ds1.file.file=classpath: degraderule.json\nspring.cloud.sentinel.datasource.ds1.file.data-type=json\n\nspring.cloud.sentinel.datasource.ds2.nacos.server-addr=127.0.0.1:8848\nspring.cloud.sentinel.datasource.ds2.nacos.dataId=sentinel\nspring.cloud.sentinel.datasource.ds2.nacos.groupId=DEFAULT_GROUP\nspring.cloud.sentinel.datasource.ds2.nacos.data-type=json\n```\n\n`ds1` 和 `ds2` 表示ReadableDataSource的名称，可随意编写。`ds1` 和 `ds2` 后面的 `file` 和 `nacos` 表示ReadableDataSource的类型。\n\n目前支持`file`, `nacos`, `zk`, `apollo`，`redis` 这5种类型。\n\n其中`nacos`，`zk`，`apollo`，`redis` 这4种类型的使用需要加上对应的依赖`sentinel-datasource-nacos`, `sentinel-datasource-zookeeper`, `sentinel-datasource-apollo`, `sentinel-datasource-redis`。\n\n当 `ReadableDataSource` 加载规则数据成功的时候，控制台会打印出相应的日志信息：\n\n```\n[Sentinel Starter] DataSource ds1-sentinel-file-datasource load 3 DegradeRule\n[Sentinel Starter] DataSource ds2-sentinel-nacos-datasource load 2 FlowRule\n```\n\n## More\nSentinel 是一款功能强大的中间件，从流量控制，熔断降级，系统负载保护等多个维度保护服务的稳定性。此 Demo 仅演示了 使用 Sentinel 作为限流工具的使用，更多 Sentinel 相关的信息，请参考 [Sentinel 项目](https://github.com/alibaba/Sentinel)。\n\n如果您对 `spring-cloud-starter-alibaba-sentinel` 有任何建议或想法，欢迎在 issue 中或者通过其他社区渠道向我们提出。\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/README.md",
    "content": "# Spring Cloud Alibaba Sentinel Example\n\n## Project description\n\nThis Example project demonstrates how to use `spring-cloud-starter-alibaba-sentinel` to complete the traffic management function in Spring Cloud applications.\n\n[Sentinel](https://github.com/alibaba/Sentinel) It is the traffic defense component of Alibaba's open source distributed system. Sentinel takes traffic as the entry point to protect the stability of services from multiple dimensions such as traffic control, fuse degradation, system load protection, etc.\n\n## Sentinel Example\n\nIn this Example project, the Sentinel circuit breaker is mainly demonstrated, and the Spring Cloud Gateway is integrated with the use of OpenFeign, RestTemplate, and Webclient.\n\n### Download and launch Sentinel Console\n\n1. First, you need to obtain the Sentinel Console, which supports direct download and source code construction\n\n   1. Direct download: [Download the Sentinel console](https://github.com/alibaba/Sentinel/releases)\n   2. Source code construction: Enter Sentinel [Github project page](https://github.com/alibaba/Sentinel), clone the code to the local compilation and packaging [参考此文档](https://github.com/alibaba/Sentinel/blob/1.8/sentinel-dashboard/README.md).\n      \n\n2. Start the console and execute the Java command `java -jar sentinel-dashboard.jar` to finish starting the Sentinel console.\n\n   The default console listening port is `8080`. The Sentinel console is developed using the Spring Boot programming model. If you need to specify other ports, please use the standard method of Spring Boot container configuration. For details, please refer to [Spring Boot documentation](https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-customizing-embedded-containers).\n\n### Sentinel Core Example\n\nThis Example module mainly demonstrates how to use the basic functions of Sentinel to complete the traffic control of Spring Cloud applications. Before launching Example for a demonstration, let's look at how to access the Sentinel component in a Spring Cloud application.\n\n#### Project preparation\n\n> **Note: This document is only for the purpose of understanding the access method. The access work is done in this sample code, and you do not need to modify it.**\n\n1. First, modify `pom.xml` the file to introduce Sentinel starter.\n\n\n   ```xml\n   <dependency>\n       <groupId>com.alibaba.cloud</groupId>\n       <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>\n   </dependency>\n   ```\n\n2. Access current-limiting buried point\n\n    -  `spring-cloud-starter-alibaba-sentinel` By default, all HTTP services provide the current limiting embedded point. If you only want to limit the current of the HTTP service, you only need to introduce the dependency and do not need to modify the code.\n\n    - Custom Buried Point If you need to limit or degrade a specific method, you can use `@SentinelResource` annotations to complete the current limiting buried point. The example code is as follows:\n\n\n      ```java\n      @SentinelResource(\"resource\")\n      public String hello() {\n          return \"Hello\";\n      }\n      ```\n\n    Of course, it can also be buried by the original `SphU.entry(xxx)` method, which can be seen [Sentinel documentation](https://github.com/alibaba/Sentinel/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8#%E5%AE%9A%E4%B9%89%E8%B5%84%E6%BA%90).\n\n3. Configure the current limit rule\n\n   Sentinel provides two ways to configure throttling rules: code configuration and console configuration. The method used in this example is configuration through code.\n\n    1. Configure rate limits by code. Here is a simple code example of rate limit configuration. For more configuration details, see [Sentinel documentation](https://github.com/alibaba/Sentinel/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8#%E5%AE%9A%E4%B9%89%E8%A7%84%E5%88%99).\n\n       ```java\n       List<FlowRule> rules = new ArrayList<FlowRule>();\n       FlowRule rule = new FlowRule();\n       rule.setResource(str);\n       // set limit qps to 10\n       rule.setCount(10);\n       rule.setGrade(RuleConstant.FLOW_GRADE_QPS);\n       rule.setLimitApp(\"default\");\n       rules.add(rule);\n       FlowRuleManager.loadRules(rules);\n       ```\n    2. Please refer to the graphic description at the end of the article for current limiting rule configuration through the console.\n\n#### The application starts\n\n1. Add configuration, and add basic configuration information in the application `/src/main/resources/application.yml`\n\n    ```yaml\n    server:\n      port: 18083\n      \n    spring:\n      application:\n        name: sentinel-core-example\n    \n      cloud:\n        sentinel:\n          transport:\n            dashboard: localhost:8080\n    ```\n\n2. Start the application, support IDE direct start and start after compilation and packaging.\n\n    1. IDE direct startup: find the main class `SentinelCoreApplication` and execute the main method to start the application.\n    2. Start after packaging and compiling: First execute `mvn clean package` to package the project compilation, and then execute `java -jar sentinel-core-example.jar` to start the application.\n\n#### Invoke service validation\n\nUse the curl command to call the two URLs separately, and you can see that the access is successful.\n\n```shell\n$ curl http://localhost:18083/test\nBlocked by Sentinel (flow limiting)\n\n$ curl http://localhost:18083/hello\nHello\n```\n\n#### Configure and verify the current limit rule\n\n1. Visit the http://localhost:8080  page and log in. The default user name and password are: `sentinel`.\n\n   On the left, you can see that the Sentinel-Example application has been registered to the console. Click **Flow control rules** it, and you can see that the current flow control rule is empty.\n\n   > ** Note: If you do not find the application in the console, please call the URL or method with Sentinel buried points, because Sentinel uses lazy load policy. For detailed troubleshooting procedures, see [Sentinel FAQ](https://github.com/alibaba/Sentinel/wiki/FAQ). **\n\n<p align=\"center\"><img src=\"https://cdn.nlark.com/lark/0/2018/png/54319/1532315951819-9ffd959e-0547-4f61-8f06-91374cfe7f21.png\" width=\"700\" heigh='400' ></p>\n\n2. Configure URL flow limit rule: click Add Flow Control Rule, fill in the URL relative path to be restricted for the resource name, select the threshold to be restricted for the single machine threshold, and click Add to confirm. (The value is set to 1 for demonstration purposes.).\n\n<p align=\"center\"><img src=\"https://cdn.yuque.com/lark/0/2018/png/54319/1532078717483-62ab74cd-e5da-4241-a45d-66166b1bde99.png\" width=\"480\" heigh='180' ></p>\n\n3. Configure custom current limiting rules: click Add a flow control rule, fill in `@SentinelResource` the value of the comment `value` field for the resource name, select the threshold for current limiting for the single machine threshold, and click Add to confirm. (The value is set to 1 for demonstration purposes.).\n\n<p align=\"center\"><img src=\"https://cdn.yuque.com/lark/0/2018/png/54319/1532080384317-2943ce0a-daaf-495d-8afc-79a0248a119a.png\" width=\"480\" heigh='180' ></p>\n\n4. Visit the URL. When the QPS exceeds 1, you can see the effect of limiting the current as follows.\n\n<p align=\"center\"><img src=\"https://cdn.yuque.com/lark/0/2018/png/54319/1532080652178-be119c4a-2a08-4f67-be70-fe5ed9a248a3.png\" width=\"480\" heigh='180' ></p>\n\n<p align=\"center\"><img src=\"https://cdn.yuque.com/lark/0/2018/png/54319/1532080661437-b84ee161-6c2d-4df2-bdb7-7cf0d5be92fb.png\" width=\"480\" heigh='180' ></p>\n\n#### Custom current limit processing logic\n\n* Default Current Limit Exception Handling\n\n  After the URL current limiting is triggered, the default processing logic is to directly return to \"Blocked by Sentinel\". If you need to customize the processing logic, the implementation method is as follows:\n\n  ```java\n  public class CustomUrlBlockHandler implements UrlBlockHandler {\n      @Override\n      public void blocked(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException {\n          // todo add your logic\n      }\n  }\n  \n  WebCallbackManager.setUrlBlockHandler(new CustomUrlBlockHandler());\n  ```\n\n* Current limit exception handling using `@SentinelResource` annotations\n\n  If you need to customize the processing logic, fill in `@SentinelResource` the attribute of the note `blockHandler` (for all types `BlockException`, you need to make your own judgment) or `fallback` the attribute (for the fuse degradation exception). **There are restrictions on the signature and location of the corresponding method** See for [Sentinel Annotation Support Document](https://github.com/alibaba/Sentinel/wiki/%E6%B3%A8%E8%A7%A3%E6%94%AF%E6%8C%81#sentinelresource-%E6%B3%A8%E8%A7%A3) details. An example implementation is as follows:\n\n  ```java\n  public class TestService {\n  \n      // blockHandler 是位于 ExceptionUtil 类下的 handleException 静态方法，需符合对应的类型限制.\n      @SentinelResource(value = \"test\", blockHandler = \"handleException\", blockHandlerClass = {ExceptionUtil.class})\n      public void test() {\n          System.out.println(\"Test\");\n      }\n  \n      // blockHandler 是位于当前类下的 exceptionHandler 方法，需符合对应的类型限制.\n      @SentinelResource(value = \"hello\", blockHandler = \"exceptionHandler\")\n      public String hello(long s) {\n          return String.format(\"Hello at %d\", s);\n      }\n  \n      public String exceptionHandler(long s, BlockException ex) {\n          // Do some log here.\n          ex.printStackTrace();\n          return \"Oops, error occurred at \" + s;\n      }\n  }\n  \n  public final class ExceptionUtil {\n  \n      public static void handleException(BlockException ex) {\n          System.out.println(\"Oops: \" + ex.getClass().getCanonicalName());\n      }\n  }\n  ```\n\nA simple `@SentinelResource` example can be found in [sentinel-demo-annotation-spring-aop](https://github.com/alibaba/Sentinel/tree/2021.x/sentinel-demo/sentinel-demo-annotation-spring-aop).\n\n### Sentinel Circuitbreaker Example\n\nThis Example mainly demonstrates the use of OpenFeign integrated Sentinel circuit breaker.\n\n#### Prepare the configuration file\n\n1. Add a configuration to the Configuration Center. DataId is `sentinel-circuitbreaker-rules.yml`\n\n   ```yml\n   feign:\n     circuitbreaker:\n       enabled: true # 开启 feign 断路器支持\n     sentinel:\n       default-rule: default # 默认规则名称\n       rules:\n         # 默认规则, 对所有 feign client 生效\n         default:\n           - grade: 2 # 根据异常数目降级\n             count: 1\n             timeWindow: 15 # 降级后到半开状态的时间\n             statIntervalMs: 1000\n             minRequestAmount: 1\n         # 只对 feign client user 生效\n         user:\n           - grade: 2\n             count: 1\n             timeWindow: 15\n             statIntervalMs: 1000\n             minRequestAmount: 1\n         # 只对 feign client user 的方法 feignMethod 生效\n         # 括号里是参数类型, 多个逗号分割, 比如 user#method(boolean,String,Map)\n         \"[user#feignMethod(boolean)]\":\n           - grade: 2\n             count: 1\n             timeWindow: 10\n             statIntervalMs: 1000\n             minRequestAmount: 1\n   ```\n\n#### Verify that the configuration is in effect\n\nStart the project main class `FeignCircuitBreakerApplication`\n\n##### Verify that the default Feign client takes effect\n\nAccess http://localhost/test/default/false  2 times (within 1 second) and then access http://localhost/test/default/true  the circuit breaker in the open state\n\n##### Verify that the specified Feign client is in effect\n\nAccess http://localhost/test/feign/false  2 times (within 1 second) and then access http://localhost/test/feign/true  the circuit breaker in the open state\n\n##### Verify that the Feign client specified method takes effect\n\nAccess http://localhost/test/feignMethod/false  2 times (within 1 second) and then access http://localhost/test/feignMethod/true  the circuit breaker in the open state\n\n#### Rule dynamic refresh\n\nModify the rules of the configuration center, and then access the above interface.\n\n### Sentinel OpenFeign Example\n\nThis Example demonstrates the integration of OpenFeing and Sentinel. In Example, httpbin is used as a background API interface service.\n\n#### Project preparation\n\n> **Note: The code in this project has completed the corresponding function and does not need to be modified.**\n\nThe project supports two startup modes: startup through the main class `OpenFeignApplication` and startup through the Jar package.\n\n#### Call the test\n\nAfter the project is started, you can access the corresponding URL to view the corresponding Sentinel flow control effect.\n\n> **Note: The RestTemplate provided in the project is the same as the Webclient Example.**\n\n## Endpoint information viewing\n\nSpring Boot applications support the exposure of relevant information through Endpoints, `spring-cloud-starter-alibaba-sentinel` as well.\n\nBefore using it, you need to add `spring-boot-starter-actuator` dependencies in Maven and allow Endpoints access in the configuration.\n* Add configuration in Spring Boot 1.x\n* Adding Configuration in Spring Boot 2.x\n\nSpring Boot 1.x can view Sentinel Endpoint information by visiting http://127.0.0.1:18083/sentinel . Spring Boot 2.x can be accessed by visiting http://127.0.0.1:18083/actuator/sentinel .\n\n<p align=\"center\"><img src=\"https://cdn.yuque.com/lark/0/2018/png/54319/1532084199224-1a41591d-7a06-4680-be8a-5de319ac635d.png\" width=\"480\" heigh='360' ></p>\n\n## View real-time monitoring\nThe Sentinel console supports real-time monitoring and viewing. You can view information such as the number of requests passed and the number of throttled flows for each link through the Sentinel console. Where `p_qps` is a pass flow controlled QPS and `b_qps` is a blocked QPS.\n\n<p align=\"center\"><img src=\"https://cdn.nlark.com/lark/0/2018/png/54319/1532313595369-8428cd7d-9eb7-4786-a149-acf0da4a2daf.png\" width=\"480\" heigh='180' ></p>\n\n## ReadableData Source support\n\nThe Sentinel provides [Implementation of ReadableDataSource by Extending Dynamic Rule](https://github.com/alibaba/Sentinel/wiki/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%99%E6%89%A9%E5%B1%95#datasource-%E6%89%A9%E5%B1%95) internally.\n\nSentinel starter incorporates several classes of ReadableDataSources that exist today. The DataSource is automatically registered in the Spring container by simply making the relevant configuration in the configuration file.\n\n `FileRefreshableDataSource` and `NacosDataSource`, configured as follows:\n\n```properties\nspring.cloud.sentinel.datasource.ds1.file.file=classpath: degraderule.json\nspring.cloud.sentinel.datasource.ds1.file.data-type=json\n\nspring.cloud.sentinel.datasource.ds2.nacos.server-addr=127.0.0.1:8848\nspring.cloud.sentinel.datasource.ds2.nacos.dataId=sentinel\nspring.cloud.sentinel.datasource.ds2.nacos.groupId=DEFAULT_GROUP\nspring.cloud.sentinel.datasource.ds2.nacos.data-type=json\n```\n\n `ds1` And `ds2` the name that represents the ReadableDataSource. Feel free to write. The sum `nacos` following `file` the `ds1` and `ds2` represents the type of the ReadableDataSource.\n\nCurrently supports `file`, `nacos`, `zk` `apollo`, `redis` these 5 types.\n\nAmong them `nacos` `zk` `apollo`, the use of `redis` these four types requires the addition of corresponding dependencies `sentinel-datasource-nacos` `sentinel-datasource-zookeeper` `sentinel-datasource-apollo` `sentinel-datasource-redis`.\n\nWhen `ReadableDataSource` the rule data is loaded successfully, the console will print out the corresponding log information:\n\n```\n[Sentinel Starter] DataSource ds1-sentinel-file-datasource load 3 DegradeRule\n[Sentinel Starter] DataSource ds2-sentinel-nacos-datasource load 2 FlowRule\n```\n\n## More\nSentinel is a powerful middleware that protects the stability of services from multiple dimensions such as flow control, fuse degradation, and system load protection. This Demo only demonstrates the use of Sentinel as a current limiting tool. For more information about Sentinel, please refer to [Project Sentinel](https://github.com/alibaba/Sentinel).\n\nIf you `spring-cloud-starter-alibaba-sentinel` have any suggestions or ideas, please feel free to send them to us in the issue or through other community channels.\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-circuitbreaker-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>sentinel-circuitbreaker-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Sentinel - Feign With Sentinel CircuitBreaker Example</name>\n    <description>Example demonstrating how to use sentinel circuit breaker with feign</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-openfeign</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-circuitbreaker-sentinel</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-circuitbreaker-example/src/main/java/com/alibaba/cloud/examples/FeignCircuitBreakerApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.openfeign.EnableFeignClients;\n\n/**\n * @author freeman\n */\n@SpringBootApplication\n@EnableFeignClients\npublic class FeignCircuitBreakerApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(FeignCircuitBreakerApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-circuitbreaker-example/src/main/java/com/alibaba/cloud/examples/controller/ApiController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.controller;\n\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n *\n *\n * @author freeman\n */\n@RestController\npublic class ApiController {\n\n\t@GetMapping(\"/default/{ok}\")\n\tpublic String defaultConfig(@PathVariable boolean ok) {\n\t\tif (ok) {\n\t\t\treturn \"ok\";\n\t\t}\n\t\tthrow new RuntimeException(\"fail\");\n\t}\n\n\t@GetMapping(\"/feign/{ok}\")\n\tpublic String feignConfig(@PathVariable boolean ok) {\n\t\tif (ok) {\n\t\t\treturn \"ok\";\n\t\t}\n\t\tthrow new RuntimeException(\"fail\");\n\t}\n\n\t@GetMapping(\"/feignMethod/{ok}\")\n\tpublic String feignMethodConfig(@PathVariable boolean ok) {\n\t\tif (ok) {\n\t\t\treturn \"ok\";\n\t\t}\n\t\tthrow new RuntimeException(\"fail\");\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-circuitbreaker-example/src/main/java/com/alibaba/cloud/examples/controller/TestController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.controller;\n\nimport com.alibaba.cloud.examples.feign.OrderClient;\nimport com.alibaba.cloud.examples.feign.UserClient;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n *\n *\n * @author freeman\n */\n@RestController\npublic class TestController {\n\n\t@Autowired\n\tprivate UserClient userClient;\n\t@Autowired\n\tprivate OrderClient orderClient;\n\n\t@GetMapping(\"/test/default/{ok}\")\n\tpublic String testDefault(@PathVariable boolean ok) {\n\t\treturn orderClient.defaultConfig(ok);\n\t}\n\n\t@GetMapping(\"/test/feign/{ok}\")\n\tpublic String testFeign(@PathVariable boolean ok) {\n\t\treturn userClient.feign(ok);\n\t}\n\n\t@GetMapping(\"/test/feignMethod/{ok}\")\n\tpublic String testFeignMethod(@PathVariable boolean ok) {\n\t\treturn userClient.feignMethod(ok);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-circuitbreaker-example/src/main/java/com/alibaba/cloud/examples/feign/OrderClient.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.feign;\n\nimport org.springframework.cloud.openfeign.FeignClient;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\n\n/**\n *\n *\n * @author freeman\n */\n@FeignClient(value = \"order\", url = \"http://localhost:${server.port}\", fallback = OrderClientFallBack.class)\npublic interface OrderClient {\n\n\t@GetMapping(\"/default/{ok}\")\n\tString defaultConfig(@PathVariable boolean ok);\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-circuitbreaker-example/src/main/java/com/alibaba/cloud/examples/feign/OrderClientFallBack.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.feign;\n\nimport org.springframework.stereotype.Component;\n\n/**\n *\n *\n * @author freeman\n */\n@Component\npublic class OrderClientFallBack implements OrderClient {\n\t@Override\n\tpublic String defaultConfig(boolean ok) {\n\t\treturn \"order fallback\";\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-circuitbreaker-example/src/main/java/com/alibaba/cloud/examples/feign/UserClient.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.feign;\n\nimport org.springframework.cloud.openfeign.FeignClient;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\n\n/**\n *\n *\n * @author freeman\n */\n@FeignClient(value = \"user\", url = \"http://localhost:${server.port}\", fallback = UserClientFallBack.class)\npublic interface UserClient {\n\n\t@GetMapping(\"/feignMethod/{ok}\")\n\tString feignMethod(@PathVariable boolean ok);\n\n\t@GetMapping(\"/feign/{ok}\")\n\tString feign(@PathVariable boolean ok);\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-circuitbreaker-example/src/main/java/com/alibaba/cloud/examples/feign/UserClientFallBack.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.feign;\n\nimport org.springframework.stereotype.Component;\n\n/**\n *\n *\n * @author freeman\n */\n@Component\npublic class UserClientFallBack implements UserClient {\n\t@Override\n\tpublic String feignMethod(boolean ok) {\n\t\treturn \"user fallback\";\n\t}\n\n\t@Override\n\tpublic String feign(boolean ok) {\n\t\treturn \"user fallback\";\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-circuitbreaker-example/src/main/resources/application.yml",
    "content": "#\n#  Copyright 2023-2024 the original author or 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\nserver:\n  port: 80\n\nspring:\n  application:\n    name: sentinel-circuit-breaker-example\n\n  cloud:\n    nacos:\n      config:\n        server-addr: 127.0.0.1:8848\n        username: 'nacos'\n        password: 'nacos'\n\n  config:\n    import: optional:nacos:sentinel-circuitbreaker-rules.yml\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-circuitbreaker-example/src/main/resources/sentinel-circuitbreaker-rules.yml",
    "content": "#\n#  Copyright 2023-2024 the original author or 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#\nspring:\n  cloud:\n    openfeign:\n      circuitbreaker:\n        enabled: true\nfeign:\n  sentinel:\n    default-rule: default\n    rules:\n      # global feign client\n      default:\n        - grade: 2\n          count: 1\n          timeWindow: 15\n          statIntervalMs: 1000\n          minRequestAmount: 1\n      # specific feign client\n      user:\n        - grade: 2\n          count: 1\n          timeWindow: 15\n          statIntervalMs: 1000\n          minRequestAmount: 1\n      # specific feign client single method\n      \"[user#feignMethod(boolean)]\":\n        - grade: 2\n          count: 1\n          timeWindow: 10\n          statIntervalMs: 1000\n          minRequestAmount: 1\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>sentinel-core-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Sentinel Core Example</name>\n    <description>Example demonstrating how to use sentinel</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-thymeleaf</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-datasource-nacos</artifactId>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/ExceptionUtil.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;\nimport com.alibaba.csp.sentinel.slots.block.BlockException;\n\nimport org.springframework.http.HttpRequest;\nimport org.springframework.http.client.ClientHttpRequestExecution;\n\n/**\n * @author fangjian\n */\npublic final class ExceptionUtil {\n\n\tprivate ExceptionUtil() {\n\n\t}\n\n\tpublic static SentinelClientHttpResponse handleException(HttpRequest request,\n\t\t\tbyte[] body, ClientHttpRequestExecution execution, BlockException ex) {\n\t\tSystem.out.println(\"Oops: \" + ex.getClass().getCanonicalName());\n\t\treturn new SentinelClientHttpResponse(\"custom block info\");\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/JsonFlowRuleListConverter.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport java.util.List;\n\nimport com.alibaba.csp.sentinel.datasource.Converter;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRule;\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.TypeReference;\n\n/**\n * @author fangjian\n */\npublic class JsonFlowRuleListConverter implements Converter<String, List<FlowRule>> {\n\n\t@Override\n\tpublic List<FlowRule> convert(String source) {\n\t\treturn JSON.parseObject(source, new TypeReference<List<FlowRule>>() {\n\t\t});\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/SentinelCoreApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport java.util.Collections;\n\nimport com.alibaba.cloud.circuitbreaker.sentinel.SentinelCircuitBreakerFactory;\nimport com.alibaba.cloud.circuitbreaker.sentinel.SentinelConfigBuilder;\nimport com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;\nimport com.alibaba.csp.sentinel.datasource.Converter;\nimport com.alibaba.csp.sentinel.slots.block.RuleConstant;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.circuitbreaker.Customizer;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author xiaojing\n */\n@SpringBootApplication\npublic class SentinelCoreApplication {\n\n\t@Bean\n\t@SentinelRestTemplate(blockHandler = \"handleException\",\n\t\t\tblockHandlerClass = ExceptionUtil.class)\n\tpublic RestTemplate restTemplate() {\n\t\treturn new RestTemplate();\n\t}\n\n\t@Bean\n\tpublic RestTemplate restTemplate2() {\n\t\treturn new RestTemplate();\n\t}\n\n\t@Bean\n\tpublic Converter myConverter() {\n\t\treturn new JsonFlowRuleListConverter();\n\t}\n\n\t@Bean\n\tpublic Customizer<SentinelCircuitBreakerFactory> defaultConfig() {\n\t\treturn factory -> {\n\t\t\tfactory.configureDefault(\n\t\t\t\t\tid -> new SentinelConfigBuilder().resourceName(id)\n\t\t\t\t\t\t\t.rules(Collections.singletonList(new DegradeRule(id)\n\t\t\t\t\t\t\t\t\t.setGrade(RuleConstant.DEGRADE_GRADE_RT).setCount(100)\n\t\t\t\t\t\t\t\t\t.setTimeWindow(10)))\n\t\t\t\t\t\t\t.build());\n\t\t};\n\t}\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(SentinelCoreApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/TestController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport com.alibaba.csp.sentinel.annotation.SentinelResource;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author xiaojing\n */\n@RestController\npublic class TestController {\n\n\t@Autowired\n\tprivate RestTemplate restTemplate;\n\n\t@Autowired\n\tprivate CircuitBreakerFactory circuitBreakerFactory;\n\n\t@GetMapping(\"/hello\")\n\t@SentinelResource(\"resource\")\n\tpublic String hello() {\n\t\treturn \"Hello\";\n\t}\n\n\t@GetMapping(\"/aa\")\n\t@SentinelResource(\"aa\")\n\tpublic String aa(int b, int a) {\n\t\treturn \"Hello test\";\n\t}\n\n\t@GetMapping(\"/test\")\n\tpublic String test1() {\n\t\treturn \"Hello test\";\n\t}\n\n\t@GetMapping(\"/template\")\n\tpublic String client() {\n\t\treturn restTemplate.getForObject(\"http://www.taobao.com/test\", String.class);\n\t}\n\n\t@GetMapping(\"/slow\")\n\tpublic String slow() {\n\t\treturn circuitBreakerFactory.create(\"slow\").run(() -> {\n\t\t\ttry {\n\t\t\t\tThread.sleep(500L);\n\t\t\t}\n\t\t\tcatch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t\treturn \"slow\";\n\t\t}, throwable -> \"fallback\");\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/WebMvcConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.servlet.config.annotation.EnableWebMvc;\nimport org.springframework.web.servlet.config.annotation.ViewControllerRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurer;\n\n/**\n * @author yuhuangbin\n */\n@Configuration\n@EnableWebMvc\npublic class WebMvcConfiguration implements WebMvcConfigurer {\n\n\t@Override\n\tpublic void addViewControllers(ViewControllerRegistry registry) {\n\t\tregistry.addViewController(\"/errorPage\").setViewName(\"errorPage\");\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.yml",
    "content": "#\n#  Copyright 2023-2024 the original author or 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\nspring:\n  application:\n    name: sentinel-core-example\n\n  cloud:\n    sentinel:\n      transport:\n        dashboard: localhost:8080\n      datasource:\n        ds1:\n          file:\n            file: classpath:flowrule.json\n            data-type: json\n            rule-type: flow\n        ds2:\n          file:\n            file: classpath:degraderule.json\n            data-type: json\n            rule-type: degrade\n        ds3:\n          file:\n              file: classpath:authority.json\n              data-type: json\n              rule-type: authority\n        ds4:\n          file:\n              file: classpath:system.json\n              data-type: json\n              rule-type: system\n        ds5:\n          file:\n              file: classpath:param-flow.json\n              data-type: json\n              rule-type: param_flow\n        ds6:\n          nacos:\n              server-addr: 127.0.0.1:8848\n              username: nacos\n              password: nacos\n              data-id: flowrule.json\n              data-type: json\n              rule-type: flow\n\n      block-page: /errorPage\n      # filter:\n      #   enabled: false\n      # http-method-specify: false\n      eager: true\n\nserver:\n  port: 18083\n\nmanagement:\n  endpoint:\n    web:\n        exposure:\n            include: \"*\"\n    health:\n      show-details: always\n      diskSpace:\n        # we can disable health check, default is enable\n        enabled: false\n      # sentinel:\n      #  enabled: false\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/authority.json",
    "content": "[\n  {\n    \"resource\": \"good\",\n    \"limitApp\": \"abc\",\n    \"strategy\": 0\n  },\n  {\n    \"resource\": \"bad\",\n    \"limitApp\": \"bcd\",\n    \"strategy\": 1\n  },\n  {\n    \"resource\": \"terrible\",\n    \"limitApp\": \"aaa\",\n    \"strategy\": 1\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/degraderule.json",
    "content": "[\n  {\n    \"resource\": \"aa\",\n    \"count\": 20.0,\n    \"grade\": 0,\n    \"passCount\": 0,\n    \"timeWindow\": 10\n  },\n  {\n    \"resource\": \"abc1\",\n    \"count\": 15.0,\n    \"grade\": 0,\n    \"passCount\": 0,\n    \"timeWindow\": 10\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/flowrule.json",
    "content": "[\n  {\n    \"resource\": \"/hello\",\n    \"controlBehavior\": 0,\n    \"count\": 1,\n    \"grade\": 1,\n    \"limitApp\": \"default\",\n    \"strategy\": 0\n  },\n  {\n    \"resource\": \"/test\",\n    \"controlBehavior\": 0,\n    \"count\": 0,\n    \"grade\": 1,\n    \"limitApp\": \"default\",\n    \"strategy\": 0\n  },\n  {\n    \"resource\": \"GET:http://www.taobao.com\",\n    \"controlBehavior\": 0,\n    \"count\": 0,\n    \"grade\": 1,\n    \"limitApp\": \"default\",\n    \"strategy\": 0\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/flowrule.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<Rules>\n    <FlowRule>\n        <resource>resource</resource>\n        <controlBehavior>0</controlBehavior>\n        <count>1</count>\n        <grade>1</grade>\n        <limitApp>default</limitApp>\n        <strategy>0</strategy>\n    </FlowRule>\n    <FlowRule>\n        <resource>test</resource>\n        <controlBehavior>0</controlBehavior>\n        <count>1</count>\n        <grade>1</grade>\n        <limitApp>default</limitApp>\n        <strategy>0</strategy>\n    </FlowRule>\n</Rules>\n\n\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/param-flow.json",
    "content": "[\n  {\n    \"resource\": \"aa\",\n    \"count\": 0,\n    \"grade\": 1,\n    \"limitApp\": \"default\",\n    \"paramIdx\": 0,\n    \"paramFlowItemList\": [\n      {\n        \"object\": \"2\",\n        \"classType\": \"int\",\n        \"count\": 1\n      }\n    ]\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/system.json",
    "content": "[\n  {\n    \"highestSystemLoad\": -1,\n    \"qps\": 100,\n    \"avgRt\": -1,\n    \"maxThread\": 10\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/templates/errorPage.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Title</title>\n</head>\n<body>\nThis is error page.\n</body>\n</html>"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-openfeign-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>sentinel-openfeign-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Sentinel x Feign - Example</name>\n    <description>Example demonstrating how to use sentinel with feign</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-openfeign</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-openfeign-example/src/main/java/com/alibaba/cloud/examples/OpenFeignApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.openfeign.EnableFeignClients;\n\n/**\n * @author raozihao\n * @author <a href=\"mailto:zihaorao@gmail.com\">Steve</a>\n */\n\n@EnableFeignClients\n@SpringBootApplication\npublic class OpenFeignApplication {\n\n\tpublic static void main(String[] args) {\n\n\t\tSpringApplication.run(OpenFeignApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-openfeign-example/src/main/java/com/alibaba/cloud/examples/configuration/EchoServiceFallbackFactory.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.configuration;\n\nimport org.springframework.cloud.openfeign.FallbackFactory;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author raozihao\n * @author <a href=\"mailto:zihaorao@gmail.com\">Steve</a>\n */\n@Component\npublic class EchoServiceFallbackFactory implements FallbackFactory<HttpbinClientFallback> {\n\t@Override\n\tpublic HttpbinClientFallback create(Throwable throwable) {\n\t\treturn new HttpbinClientFallback(throwable);\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-openfeign-example/src/main/java/com/alibaba/cloud/examples/configuration/HttpbinClient.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.configuration;\n\n\nimport org.springframework.cloud.openfeign.FeignClient;\nimport org.springframework.web.bind.annotation.GetMapping;\n\n/**\n * Provide the external exposure interface of the service calling client.\n *\n * @author raozihao\n * @author <a href=\"mailto:zihaorao@gmail.com\">Steve</a>\n */\n@FeignClient(name = \"openfeign-example\", url = \"https://httpbin.org\", contextId = \"openfeign-example\", fallbackFactory = EchoServiceFallbackFactory.class)\npublic interface HttpbinClient {\n\n\t@GetMapping(\"/delay/3\")\n\tString delay();\n\n\t@GetMapping(\"/status/500\")\n\tString status500();\n\n\n\t@GetMapping(\"/get\")\n\tString get();\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-openfeign-example/src/main/java/com/alibaba/cloud/examples/configuration/HttpbinClientFallback.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.configuration;\n\n\n/**\n * When the service is blown, the fallback operation is performed.\n *\n * @author raozihao\n */\npublic class HttpbinClientFallback implements HttpbinClient {\n\n\t@Override\n\tpublic String delay() {\n\t\treturn \"delay degrade by sentinel\";\n\t}\n\n\t@Override\n\tpublic String status500() {\n\t\treturn \"500 degrade by sentinel\";\n\t}\n\n\t@Override\n\tpublic String get() {\n\t\treturn \"get degrade by sentinel\";\n\t}\n\n\tprivate Throwable throwable;\n\n\tHttpbinClientFallback(Throwable throwable) {\n\t\tthis.throwable = throwable;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-openfeign-example/src/main/java/com/alibaba/cloud/examples/configuration/SentinelRulesConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.configuration;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport com.alibaba.csp.sentinel.slots.block.RuleConstant;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;\nimport jakarta.annotation.PostConstruct;\n\nimport org.springframework.stereotype.Component;\n\n/**\n * @author raozihao\n * @author <a href=\"mailto:zihaorao@gmail.com\">Steve</a>\n */\n@Component\npublic class SentinelRulesConfiguration {\n\n\t/**\n\t * You can configure sentinel rules by referring.\n\t * https://sca.aliyun.com/docs/2023/user-guide/sentinel/advanced-guide/#%E6%9B%B4%E5%A4%9A%E9%85%8D%E7%BD%AE%E9%A1%B9\n\t */\n\t@PostConstruct\n\tpublic void init() {\n\t\tSystem.out.println(\"Load Sentinel Rules start！\");\n\t\tList<FlowRule> flowRules = new ArrayList<FlowRule>();\n\t\tFlowRule flowRule = new FlowRule();\n\t\tflowRule.setResource(\"GET:https://httpbin.org/get\");\n\t\tflowRule.setCount(1);\n\t\tflowRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);\n\t\tflowRule.setStrategy(RuleConstant.STRATEGY_DIRECT);\n\t\tflowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);\n\t\tflowRule.setLimitApp(\"default\");\n\t\tflowRules.add(flowRule);\n\t\tFlowRuleManager.loadRules(flowRules);\n\n\t\tList<DegradeRule> degradeRules = new ArrayList<DegradeRule>();\n\t\tDegradeRule degradeRule1 = new DegradeRule();\n\t\tdegradeRule1.setResource(\"GET:https://httpbin.org/status/500\");\n\t\tdegradeRule1.setCount(1);\n\t\tdegradeRule1.setMinRequestAmount(1);\n\t\tdegradeRule1.setTimeWindow(30);\n\t\tdegradeRule1.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);\n\t\tdegradeRule1.setLimitApp(\"default\");\n\t\tdegradeRules.add(degradeRule1);\n\n\t\tDegradeRule degradeRule2 = new DegradeRule();\n\t\tdegradeRule2.setResource(\"GET:https://httpbin.org/delay/3\");\n\t\tdegradeRule2.setCount(1);\n\t\tdegradeRule2.setGrade(RuleConstant.DEGRADE_GRADE_RT);\n\t\tdegradeRule2.setSlowRatioThreshold(0.1);\n\t\tdegradeRule2.setMinRequestAmount(1);\n\t\tdegradeRule2.setTimeWindow(30);\n\t\tdegradeRule2.setLimitApp(\"default\");\n\t\tdegradeRules.add(degradeRule2);\n\t\tDegradeRuleManager.loadRules(degradeRules);\n\t\tSystem.out.println(\"Load Sentinel Rules end！\");\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-openfeign-example/src/main/java/com/alibaba/cloud/examples/controller/TestController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.controller;\n\nimport com.alibaba.cloud.examples.configuration.HttpbinClient;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author raozihao\n * @author <a href=\"mailto:zihaorao@gmail.com\">Steve</a>\n */\n@RestController\npublic class TestController {\n\n\t@Autowired\n\tprivate HttpbinClient httpbinClient;\n\n\t@GetMapping(\"/rt\")\n\tpublic String delay() {\n\t\treturn httpbinClient.delay();\n\t}\n\n\t@GetMapping(\"/exp\")\n\tpublic String exp() {\n\t\treturn httpbinClient.status500();\n\t}\n\n\t@GetMapping(\"/get\")\n\tpublic String get() {\n\t\treturn httpbinClient.get();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-openfeign-example/src/main/resources/application.yml",
    "content": "#\n#  Copyright 2023-2024 the original author or 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\nserver:\n  port: 18087\n\nspring:\n  application:\n    name: sentinel-openfeign-example\n\n  cloud:\n    sentinel:\n      transport:\n        dashboard: localhost:8080\n      eager: true\n#  Don't support run in jar by using configuration file method now, refer to https://github.com/alibaba/spring-cloud-alibaba/issues/3033\n#      datasource:\n#        ds1.file:\n#          file: \"classpath: degraderule.json\"\n#          ruleType: \"degrade\"\n#          dataType: \"json\"\n#        ds2.file:\n#          file: \"classpath: flowrule.json\"\n#          ruleType: \"flow\"\n#          dataType: \"json\"\n\nfeign:\n  sentinel:\n    enabled: true\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-openfeign-example/src/main/resources/degraderule.json",
    "content": "[\n  {\n    \"resource\": \"GET:https://httpbin.org/status/500\",\n    \"count\": 1,\n    \"grade\": 2,\n    \"minRequestAmount\": 1,\n    \"timeWindow\": 30\n  },\n  {\n    \"resource\": \"GET:https://httpbin.org/delay/3\",\n    \"count\": 1,\n    \"grade\": 0,\n    \"slowRatioThreshold\": 0.1,\n    \"minRequestAmount\": 1,\n    \"timeWindow\": 30\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-openfeign-example/src/main/resources/flowrule.json",
    "content": "[\n  {\n    \"resource\": \"GET:https://httpbin.org/get\",\n    \"controlBehavior\": 0,\n    \"count\": 1,\n    \"grade\": 1,\n    \"limitApp\": \"default\",\n    \"strategy\": 0\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-resttemplate-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>sentinel-resttemplate-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Sentinel x RestTemplate - Example</name>\n    <description>Example demonstrating how to use sentinel with RestTemplate</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-resttemplate-example/src/main/java/com/alibaba/cloud/examples/RestTemplateApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * @author raozihao\n * @author <a href=\"mailto:zihaorao@gmail.com\">Steve</a>\n */\n@SpringBootApplication\npublic class RestTemplateApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(RestTemplateApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-resttemplate-example/src/main/java/com/alibaba/cloud/examples/configuration/RestTemplateConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.configuration;\n\n\nimport com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;\n\nimport org.springframework.cloud.client.loadbalancer.LoadBalanced;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author raozihao\n * @author <a href=\"mailto:zihaorao@gmail.com\">Steve</a>\n */\n@Configuration\npublic class RestTemplateConfiguration {\n\n\t@LoadBalanced\n\t@Bean\n\t@SentinelRestTemplate\n\tpublic RestTemplate restTemplate() {\n\t\treturn new RestTemplate();\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-resttemplate-example/src/main/java/com/alibaba/cloud/examples/configuration/SentinelRulesConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.configuration;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport com.alibaba.csp.sentinel.slots.block.RuleConstant;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;\nimport jakarta.annotation.PostConstruct;\n\nimport org.springframework.stereotype.Component;\n\n/**\n * @description\n * @author ChengPu raozihao\n * @date 2023/2/11\n */\n@Component\npublic class SentinelRulesConfiguration {\n\t/**\n\t * You can configure sentinel rules by referring.\n\t * https://sca.aliyun.com/docs/2023/user-guide/sentinel/advanced-guide/#%E6%9B%B4%E5%A4%9A%E9%85%8D%E7%BD%AE%E9%A1%B9\n\t */\n\t@PostConstruct\n\tpublic void init() {\n\t\tSystem.out.println(\"Load Sentinel Rules start！\");\n\t\tList<FlowRule> flowRules = new ArrayList<FlowRule>();\n\t\tFlowRule flowRule = new FlowRule();\n\t\tflowRule.setResource(\"GET:https://httpbin.org/get\");\n\t\tflowRule.setCount(1);\n\t\tflowRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);\n\t\tflowRule.setStrategy(RuleConstant.STRATEGY_DIRECT);\n\t\tflowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);\n\t\tflowRule.setLimitApp(\"default\");\n\t\tflowRules.add(flowRule);\n\t\tFlowRuleManager.loadRules(flowRules);\n\n\t\tList<DegradeRule> degradeRules = new ArrayList<DegradeRule>();\n\t\tDegradeRule degradeRule1 = new DegradeRule();\n\t\tdegradeRule1.setResource(\"GET:https://httpbin.org/status/500\");\n\t\tdegradeRule1.setCount(1);\n\t\tdegradeRule1.setMinRequestAmount(1);\n\t\tdegradeRule1.setTimeWindow(30);\n\t\tdegradeRule1.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);\n\t\tdegradeRule1.setLimitApp(\"default\");\n\t\tdegradeRules.add(degradeRule1);\n\n\t\tDegradeRule degradeRule2 = new DegradeRule();\n\t\tdegradeRule2.setResource(\"GET:https://httpbin.org/delay/3\");\n\t\tdegradeRule2.setCount(1);\n\t\tdegradeRule2.setGrade(RuleConstant.DEGRADE_GRADE_RT);\n\t\tdegradeRule2.setSlowRatioThreshold(0.1);\n\t\tdegradeRule2.setMinRequestAmount(1);\n\t\tdegradeRule2.setTimeWindow(30);\n\t\tdegradeRule2.setLimitApp(\"default\");\n\t\tdegradeRules.add(degradeRule2);\n\t\tDegradeRuleManager.loadRules(degradeRules);\n\t\tSystem.out.println(\"Load Sentinel Rules end！\");\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-resttemplate-example/src/main/java/com/alibaba/cloud/examples/controller/TestController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.controller;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author raozihao\n * @author <a href=\"mailto:zihaorao@gmail.com\">Steve</a>\n */\n@RestController\npublic class TestController {\n\n\t@Autowired\n\tRestTemplate restTemplate;\n\n\t@GetMapping(\"/exp\")\n\tpublic String exp() {\n\t\treturn restTemplate.getForObject(\"https://httpbin.org/status/500\", String.class);\n\t}\n\n\t@GetMapping(\"/rt\")\n\tpublic String rt() {\n\t\treturn restTemplate.getForObject(\"https://httpbin.org/delay/3\", String.class);\n\t}\n\n\t@GetMapping(\"/get\")\n\tpublic String get() {\n\t\treturn restTemplate.getForObject(\"https://httpbin.org/get\", String.class);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-resttemplate-example/src/main/resources/application.yml",
    "content": "#\n#  Copyright 2023-2024 the original author or 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\nserver:\n  port: 18088\n\nspring:\n  application:\n    name: sentinel-resttemplate-example\n\n  cloud:\n    sentinel:\n      transport:\n        dashboard: localhost:8080\n      eager: true\n\n#  Don't support run in jar by using configuration file method now, refer to https://github.com/alibaba/spring-cloud-alibaba/issues/3033\n#  cloud:\n#    sentinel:\n#      datasource:\n#        ds1.file:\n#          file: \"classpath: degraderule.json\"\n#          ruleType: \"degrade\"\n#          dataType: \"json\"\n#        ds2.file:\n#          file: \"classpath: flowrule.json\"\n#          ruleType: \"flow\"\n#          dataType: \"json\"\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-resttemplate-example/src/main/resources/degraderule.json",
    "content": "[\n  {\n    \"resource\": \"GET:https://httpbin.org/status/500\",\n    \"count\": 1,\n    \"grade\": 2,\n    \"minRequestAmount\": 1,\n    \"timeWindow\": 30\n  },\n  {\n    \"resource\": \"GET:https://httpbin.org/delay/3\",\n    \"count\": 1,\n    \"grade\": 0,\n    \"slowRatioThreshold\": 0.1,\n    \"minRequestAmount\": 1,\n    \"timeWindow\": 30\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-resttemplate-example/src/main/resources/flowrule.json",
    "content": "[\n  {\n    \"resource\": \"GET:https://httpbin.org/get\",\n    \"controlBehavior\": 0,\n    \"count\": 1,\n    \"grade\": 1,\n    \"limitApp\": \"default\",\n    \"strategy\": 0\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-resttemplate-example/src/test/java/com/alibaba/cloud/examples/RestTemplateApplicationTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.junit.jupiter.api.Disabled;\nimport org.junit.jupiter.api.Test;\n\n/**\n * Test {@link RestTemplateApplication}.\n *\n * @author wangliang181230\n */\n@Disabled(\"For debugging\")\npublic class RestTemplateApplicationTest {\n\n\t/**\n\t * Please run this test after execute `mvn clean install -Pnative -e` .\n\t *\n\t * @throws Exception the exception\n\t */\n\t@Test\n\tpublic void runWithSpringAotModeAfterProcessAot() throws Exception {\n\t\t// Enable spring-aot-mode\n\t\tSystem.setProperty(\"spring.aot.enabled\", \"true\");\n\n\t\t// Start the application\n\t\tRestTemplateApplication.main(new String[0]);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>sentinel-spring-cloud-gateway-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Sentinel x Gateway Example</name>\n    <description>Example demonstrating how to use sentinel with spring cloud gateway</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-webflux</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-gateway-server-webflux</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>\n        </dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba.csp</groupId>\n\t\t\t<artifactId>sentinel-datasource-extension</artifactId>\n\t\t</dependency>\n\n        <!--<dependency>-->\n        <!--<groupId>com.alibaba.csp</groupId>-->\n        <!--<artifactId>sentinel-datasource-nacos</artifactId>-->\n        <!--</dependency>-->\n        <!--<dependency>-->\n        <!--<groupId>com.alibaba.csp</groupId>-->\n        <!--<artifactId>sentinel-datasource-zookeeper</artifactId>-->\n        <!--</dependency>-->\n        <!--<dependency>-->\n        <!--<groupId>com.alibaba.csp</groupId>-->\n        <!--<artifactId>sentinel-datasource-apollo</artifactId>-->\n        <!--</dependency>-->\n        <!-- define in spring-boot-autoconfigure module -->\n        <!--<dependency>-->\n        <!--<groupId>com.fasterxml.jackson.dataformat</groupId>-->\n        <!--<artifactId>jackson-dataformat-xml</artifactId>-->\n        <!--</dependency>-->\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/java/com/alibaba/cloud/examples/MySCGConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;\nimport reactor.core.publisher.Mono;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.http.MediaType;\nimport org.springframework.web.reactive.function.server.ServerResponse;\nimport org.springframework.web.server.ServerWebExchange;\n\nimport static org.springframework.web.reactive.function.BodyInserters.fromValue;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@Configuration\npublic class MySCGConfiguration {\n\n\t@Bean\n\tpublic BlockRequestHandler blockRequestHandler() {\n\t\treturn new BlockRequestHandler() {\n\t\t\t@Override\n\t\t\tpublic Mono<ServerResponse> handleRequest(ServerWebExchange exchange,\n\t\t\t\t\tThrowable t) {\n\t\t\t\treturn ServerResponse.status(444).contentType(MediaType.APPLICATION_JSON)\n\t\t\t\t\t\t.body(fromValue(\"SCS Sentinel block\"));\n\t\t\t}\n\t\t};\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/java/com/alibaba/cloud/examples/RulesWebFluxController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport java.util.List;\nimport java.util.Set;\n\nimport com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;\nimport com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;\nimport com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;\nimport com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;\nimport reactor.core.publisher.Mono;\n\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@RestController\npublic class RulesWebFluxController {\n\n\t@GetMapping(\"/api\")\n\tpublic Mono<Set<ApiDefinition>> apiRules() {\n\t\treturn Mono.just(GatewayApiDefinitionManager.getApiDefinitions());\n\t}\n\n\t@GetMapping(\"/gateway\")\n\tpublic Mono<Set<GatewayFlowRule>> apiGateway() {\n\t\treturn Mono.just(GatewayRuleManager.getRules());\n\t}\n\n\t@GetMapping(\"/flow\")\n\tpublic Mono<List<FlowRule>> apiFlow() {\n\t\treturn Mono.just(FlowRuleManager.getRules());\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/java/com/alibaba/cloud/examples/SentinelSpringCloudGatewayApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@SpringBootApplication\npublic class SentinelSpringCloudGatewayApplication {\n\n\tpublic static void main(String[] args) {\n\n\t\t// GatewayCallbackManager.setRequestOriginParser(s -> \"123\");\n\t\tSpringApplication.run(SentinelSpringCloudGatewayApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/resources/api.json",
    "content": "[\n  {\n    \"apiName\": \"some_customized_api\",\n    \"predicateItems\": [\n      {\n        \"pattern\": \"/product/baz\"\n      },\n      {\n        \"pattern\": \"/product/foo/**\",\n        \"matchStrategy\": 1\n      },\n      {\n        \"items\": [\n          {\n            \"pattern\": \"/spring-cloud/**\"\n          },\n          {\n            \"pattern\": \"/spring-cloud-alibaba/**\"\n          }\n        ]\n      }\n    ]\n  },\n  {\n    \"apiName\": \"another_customized_api\",\n    \"predicateItems\": [\n      {\n        \"pattern\": \"/ahas\"\n      }\n    ]\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/resources/application.yaml",
    "content": "#\n#  Copyright 2023-2024 the original author or 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\nserver:\n  port: 18085\n\nspring:\n  application:\n    name: sentinel-spring-cloud-gateway\n\n  cloud:\n    gateway:\n      enabled: true\n      discovery:\n        locator:\n          lower-case-service-id: true\n      routes:\n      # Add your routes here.\n      - id: aliyun_route\n        uri: https://www.aliyun.com/\n        predicates:\n        - Path=/product/**\n      - id: httpbin_route\n        uri: https://httpbin.org\n        predicates:\n        - Path=/httpbin/**\n        filters:\n        - RewritePath=/httpbin/(?<segment>.*), /$\\{segment}\n\n    sentinel:\n      datasource.ds2.file:\n        file: \"classpath: gateway.json\"\n        ruleType: gw-flow\n      datasource.ds1.file:\n        file: \"classpath: api.json\"\n        ruleType: gw-api-group\n      transport:\n        dashboard: localhost:8080\n      eager: true\n      filter:\n        enabled: true\n      scg.fallback:\n          mode: response\n          response-status: 444\n          response-body: 1234\n      scg:\n        order: -100\n\nmanagement:\n  endpoints:\n    web:\n      exposure:\n        include: \"*\"\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/resources/gateway.json",
    "content": "[\n  {\n    \"resource\": \"some_customized_api\",\n    \"count\": 1\n  },\n  {\n    \"resource\": \"httpbin_route\",\n    \"count\": 0,\n    \"paramItem\": {\n      \"parseStrategy\": 2,\n      \"fieldName\": \"Spring-Cloud-Alibaba\"\n    }\n  },\n  {\n    \"resource\": \"httpbin_route\",\n    \"count\": 0,\n    \"paramItem\": {\n      \"parseStrategy\": 3,\n      \"fieldName\": \"name\"\n    }\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-webflux-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <artifactId>sentinel-webflux-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Sentinel x WebFlux Example</name>\n    <description>Example demonstrating how to use sentinel with webflux</description>\n    <packaging>jar</packaging>\n\n\n    <dependencies>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-webflux</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n\n        <!--<dependency>-->\n        <!--<groupId>com.alibaba.csp</groupId>-->\n        <!--<artifactId>sentinel-datasource-nacos</artifactId>-->\n        <!--</dependency>-->\n        <!--<dependency>-->\n        <!--<groupId>com.alibaba.csp</groupId>-->\n        <!--<artifactId>sentinel-datasource-zookeeper</artifactId>-->\n        <!--</dependency>-->\n        <!--<dependency>-->\n        <!--<groupId>com.alibaba.csp</groupId>-->\n        <!--<artifactId>sentinel-datasource-apollo</artifactId>-->\n        <!--</dependency>-->\n        <!-- define in spring-boot-autoconfigure module -->\n        <!--<dependency>-->\n        <!--<groupId>com.fasterxml.jackson.dataformat</groupId>-->\n        <!--<artifactId>jackson-dataformat-xml</artifactId>-->\n        <!--</dependency>-->\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-webflux-example/src/main/java/com/alibaba/cloud/examples/MyConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport java.util.Collections;\n\nimport com.alibaba.cloud.circuitbreaker.sentinel.ReactiveSentinelCircuitBreakerFactory;\nimport com.alibaba.cloud.circuitbreaker.sentinel.SentinelConfigBuilder;\nimport com.alibaba.csp.sentinel.adapter.spring.webflux.callback.BlockRequestHandler;\nimport com.alibaba.csp.sentinel.slots.block.RuleConstant;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\nimport reactor.core.publisher.Mono;\n\nimport org.springframework.cloud.client.circuitbreaker.Customizer;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\nimport org.springframework.web.reactive.function.server.ServerResponse;\nimport org.springframework.web.server.ServerWebExchange;\n\nimport static org.springframework.web.reactive.function.BodyInserters.fromValue;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@Configuration\npublic class MyConfiguration {\n\n\t@Bean\n\tpublic BlockRequestHandler blockRequestHandler() {\n\t\treturn new BlockRequestHandler() {\n\t\t\t@Override\n\t\t\tpublic Mono<ServerResponse> handleRequest(ServerWebExchange exchange,\n\t\t\t\t\tThrowable t) {\n\t\t\t\treturn ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)\n\t\t\t\t\t\t.contentType(MediaType.APPLICATION_JSON).body(fromValue(\"block\"));\n\t\t\t}\n\t\t};\n\t}\n\n\t@Bean\n\tpublic Customizer<ReactiveSentinelCircuitBreakerFactory> slowCustomizer() {\n\t\treturn factory -> {\n\t\t\tfactory.configure(builder -> builder.rules(Collections.singletonList(\n\t\t\t\t\tnew DegradeRule(\"slow_mono\").setGrade(RuleConstant.DEGRADE_GRADE_RT)\n\t\t\t\t\t\t\t.setCount(100).setTimeWindow(5))),\n\t\t\t\t\t\"slow_mono\");\n\t\t\tfactory.configure(builder -> builder.rules(Collections.singletonList(\n\t\t\t\t\tnew DegradeRule(\"slow_flux\").setGrade(RuleConstant.DEGRADE_GRADE_RT)\n\t\t\t\t\t\t\t.setCount(100).setTimeWindow(5))),\n\t\t\t\t\t\"slow_flux\");\n\t\t\tfactory.configureDefault(id -> new SentinelConfigBuilder().resourceName(id)\n\t\t\t\t\t.rules(Collections.singletonList(new DegradeRule(id)\n\t\t\t\t\t\t\t.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT)\n\t\t\t\t\t\t\t.setCount(0.5).setTimeWindow(10)))\n\t\t\t\t\t.build());\n\t\t};\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-webflux-example/src/main/java/com/alibaba/cloud/examples/SentinelWebFluxApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@SpringBootApplication\npublic class SentinelWebFluxApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(SentinelWebFluxApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-webflux-example/src/main/java/com/alibaba/cloud/examples/SentinelWebFluxController.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples;\n\nimport com.alibaba.csp.sentinel.adapter.reactor.SentinelReactorTransformer;\nimport reactor.core.publisher.Flux;\nimport reactor.core.publisher.Mono;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.reactive.function.client.WebClient;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@RestController\npublic class SentinelWebFluxController {\n\n\t@Autowired\n\tprivate ReactiveCircuitBreakerFactory circuitBreakerFactory;\n\n\t@GetMapping(\"/mono\")\n\tpublic Mono<String> mono() {\n\t\treturn Mono.just(\"simple string\")\n\t\t\t\t// transform the publisher here.\n\t\t\t\t.transform(new SentinelReactorTransformer<>(\"mono\"));\n\t}\n\n\t@GetMapping(\"/test\")\n\tpublic Mono<String> test() {\n\t\treturn Mono.just(\"simple string\")\n\t\t\t\t// transform the publisher here.\n\t\t\t\t.transform(new SentinelReactorTransformer<>(\"test\"));\n\t}\n\n\t@GetMapping(\"/flux\")\n\tpublic Flux<String> flux() {\n\t\treturn Flux.fromArray(new String[] { \"a\", \"b\", \"c\" })\n\t\t\t\t// transform the publisher here.\n\t\t\t\t.transform(new SentinelReactorTransformer<>(\"flux\"));\n\t}\n\n\t@GetMapping(\"/cbSlow\")\n\tpublic Mono<String> cbSlow() {\n\t\tint delaySecs = 2;\n\t\treturn WebClient.builder().baseUrl(\"http://httpbin.org/\").build().get()\n\t\t\t\t.uri(\"/delay/\" + delaySecs).retrieve().bodyToMono(String.class)\n\t\t\t\t.transform(it -> circuitBreakerFactory.create(\"slow_mono\").run(it, t -> {\n\t\t\t\t\tt.printStackTrace();\n\t\t\t\t\treturn Mono.just(\"fallback\");\n\t\t\t\t}));\n\t}\n\n\t@GetMapping(\"/cbError\")\n\tpublic Mono<String> cbError() {\n\t\tString code = \"500\";\n\t\treturn WebClient.builder().baseUrl(\"http://httpbin.org/\").build().get()\n\t\t\t\t.uri(\"/status/\" + code).retrieve().bodyToMono(String.class)\n\t\t\t\t.transform(it -> circuitBreakerFactory.create(\"cbError\").run(it, t -> {\n\t\t\t\t\tt.printStackTrace();\n\t\t\t\t\treturn Mono.just(\"fallback\");\n\t\t\t\t}));\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-webflux-example/src/main/resources/application.yml",
    "content": "#\n#  Copyright 2023-2024 the original author or 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\nserver:\n  port: 18084\n\nspring:\n  application:\n    name: sentinel-webflux-example\n\n  cloud:\n    sentinel:\n      transport:\n        dashboard: localhost:8080\n      eager: true\n      datasource:\n        ds1:\n          file:\n            file: classpath:flowrule.json\n            data-type: json\n            rule-type: flow\n\nmanagement:\n  endpoints:\n    web:\n      exposure:\n        include=*:\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/sentinel-example/sentinel-webflux-example/src/main/resources/flowrule.json",
    "content": "[\n  {\n    \"resource\": \"/mono\",\n    \"controlBehavior\": 0,\n    \"count\": 0,\n    \"grade\": 1,\n    \"limitApp\": \"default\",\n    \"strategy\": 0\n  },\n  {\n    \"resource\": \"/flux\",\n    \"controlBehavior\": 0,\n    \"count\": 0,\n    \"grade\": 1,\n    \"limitApp\": \"default\",\n    \"strategy\": 0\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/node-service.js",
    "content": "/*\n * Copyright 2013-2023 the original author or 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\nvar http = require('http');\nvar url = require(\"url\");\nvar path = require('path');\n\n// 创建server\nvar server = http.createServer(function(req, res) {\n    // 获得请求的路径\n    var pathname = url.parse(req.url).pathname;\n    res.writeHead(200, { 'Content-Type' : 'application/json; charset=utf-8' });\n    // 访问http://localhost:8060/，将会返回{\"index\":\"欢迎来到首页\"}\n    if (pathname === '/') {\n        res.end(JSON.stringify({ \"index\" : \"欢迎来到首页\" }));\n    }\n    // 访问http://localhost:8060/health，将会返回{\"status\":\"UP\"}\n    else if (pathname === '/health.json') {\n        res.end(JSON.stringify({ \"status\" : \"UP\" }));\n    }\n    // 其他情况返回404\n    else {\n        res.end(\"404\");\n    }\n});\n// 创建监听，并打印日志\nserver.listen(8060, function() {\n    console.log('listening on localhost:8060');\n});"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/readme-zh.md",
    "content": "# Spring Cloud Alibaba Sidecar Example\n\n## 项目说明\n\n本项目演示如何使用 Nacos + Spring Cloud Alibaba Sidecar 完成 异构语言微服务的接入。\n\n[Spring Cloud Alibaba Sidecar](https://spring-cloud-alibaba-group.github.io/github-pages/hoxton/zh-cn/index.html#_spring_cloud_alibaba_sidecar)  是一个用来快速完美整合 Spring Cloud 与 异构语言微服务 的框架\n\n\n\n## 准备工作\n\n### 下载并启动 Nacos\n\n**在接入 Sidecar 之前，首先需要启动 Nacos服务器。**\n\n1. 下载[Nacos二进制文件](https://github.com/alibaba/nacos/releases/download/2.1.0/nacos-server-2.1.0.zip) 并解压\n\n2. 启动 Nacos Server\n   \n   下载解压后 我们需要进入到 bin 目录启动 nacos 服务， 一定不要双击启动，双击默认会以集群方式启动，我们以单机方式启动。\n```bash\nstartup.cmd -m standalone\n```\n\n3. 登录 Nacos\n   \n   我们来到浏览器 输入localhost:8848/nacos 可以看到Nacos的运行的界面\n   用户名和密码都是 `nacos`\n\n\n## 简单示例\n本文以Nacos作为注册中心为例，Sidecar接入一个非Java语言的服务。\n\n\n### Step1: 引入依赖\n\n修改 `pom.xml` 文件，引入 Spring Cloud Alibaba Sidecar Starter。\n\n```xml\n\n<dependency>\n    <groupId>org.springframework.cloud</groupId>\n    <artifactId>spring-cloud-starter-gateway-server-webflux</artifactId>\n</dependency>\n\n<dependency>\n    <groupId>com.alibaba.cloud</groupId>\n    <artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>\n</dependency>\n\n<dependency>\n    <groupId>com.alibaba.cloud</groupId>\n    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n</dependency>\n\n```\n\n### Step2: 配置 Sidecar 相关信息\n然后在项目的application.yml 文件中指定以下配置\n```yaml\nserver:\n   port: 8070\nspring:\n   cloud:\n      nacos:\n         username: nacos\n         password: nacos\n         discovery:\n            server-addr: 127.0.0.1:8848\n            group: test\n      gateway:\n         discovery:\n            locator:\n               enabled: true\n\n   application:\n      name: node-service\n# sidecar 相关的配置\nsidecar:\n   # 异构微服务的IP\n   ip: 127.0.0.1\n   # 异构微服务的端口\n   port: 8060\n\n   # 异构微服务的健康检查URL(这里不配置的话，默认会认为是UP)\n   health-check-url: http://localhost:8060/health.json\n# springboot actuator监控相关\nmanagement:\n   endpoint:\n      health:\n         show-details: always\n```\n注意：这里的 localhost:8060，是我本机起了一个nginx 代理了这个health.json的请求。在实际使用过程中可以是任意的REST服务，只需要返回正确的JSON格式的健康检测数据即可。\n```json\n\n{\n  \"status\": \"DOWN\"\n}\n```\n\n### Step3: 启动应用\n之后分别启动 Sidecar 服务、本地异构服务。\n\nIDE 直接启动：找到主类 `com.alibaba.cloud.sidecar.DemoApplication`，执行 main 方法启动应用。\n\n注意：本文是以 `spring-cloud-alibaba-sidecar-nacos-example`项目为例，所以启动的是它下面的`DemoApplication`启动类。\n![idea.png](https://cdn.nlark.com/yuque/0/2022/png/1752280/1662550869316-98d574af-d1ba-4c00-a0af-5e33e13075fd.png)\n\n### Step4: 查看服务注册情况\n\n![nacos.png](https://cdn.nlark.com/yuque/0/2022/png/1752280/1662548324337-566cc824-4d08-4041-ac83-1968c7347a9e.png)\n\n\n\n\n### Step4: 访问异构服务\n完成上面4步，我们发现对应的服务`node-service`已经成功注册到了注册中心。此时，这个服务已经成功的融入到了Spring Cloud 微服务的怀抱。对于Spring Cloud 微服务而言，访问它跟访问其它的Java微服务没有任何的区别。\n而这，也正是 Spring Cloud Alibaba Sidecar的魅力所在。接下来，我们将继续演示怎样访问这个服务。\n\n浏览器访问\nhttp://127.0.0.1:8070/node-service/health.json\n能调通则说明整合成功。\n\n![](https://cdn.nlark.com/yuque/0/2022/png/1752280/1662549893322-1b7a761a-ecd7-44ae-88b6-872eca43a866.png)\n\n## More\n\n如果您对 spring cloud starter alibaba sidecar 有任何建议或想法，欢迎在 issue 中或者通过其他社区渠道向我们提出。\n\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/readme.md",
    "content": "# Spring Cloud Alibaba Sidecar Example\n\n## Project Instruction\n\nThis project demonstrates how to use `Nacos + Spring Cloud Alibaba Sidecar` to access heterogeneous language microservices.\n\n[Spring Cloud Alibaba Sidecar](https://spring-cloud-alibaba-group.github.io/github-pages/hoxton/zh-cn/index.html#_spring_cloud_alibaba_sidecar)  is a framework for fast and seamless integration of Spring Cloud with heterogeneous language microservices.\n\n\n\n## Preparation\n\n### Download and Startup Nacos\n\n**You should startup Nacos Server before using Sidecar**\n\n1. Download [Nacos](https://archive.apache.org/dist/rocketmq/4.3.2/rocketmq-all-4.3.2-bin-release.zip) and unzip it.\n\n2. Startup Name Server\n\n```bash\nstartup.cmd -m standalone\n```\n\n3. Sign in Nacos\n   \n   Open you browser then input `localhost:8848/nacos` ,you can see the Nacos dashboard ui .\n   The default username and password are `nacos`\n\n\n## Simple example\nIn this paper, Sidecar accesses a non-Java language service using Nacos as a registry as an example.\n\n\n### Step1: Declare dependency\nAdd dependency spring-cloud-starter-alibaba-sidecar to the `pom.xml` file in your Sidecar project.\n\n```xml\n<dependency>\n    <groupId>org.springframework.cloud</groupId>\n    <artifactId>spring-cloud-starter-gateway-server-webflux</artifactId>\n</dependency>\n\n<dependency>\n    <groupId>com.alibaba.cloud</groupId>\n    <artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>\n</dependency>\n\n<dependency>\n    <groupId>com.alibaba.cloud</groupId>\n    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n</dependency>\n```\n\n### Step2: Configure sidecar\nThen add necessary configurations to file `/src/main/resources/application.yml`.\n```yaml\nserver:\n   port: 8070\nspring:\n   cloud:\n      nacos:\n         username: nacos\n         password: nacos\n         discovery:\n            server-addr: 127.0.0.1:8848\n            group: test\n      gateway:\n         discovery:\n            locator:\n               enabled: true\n\n   application:\n      name: node-service\nsidecar:\n  # heterogeneous service‘s ip\n  ip: 127.0.0.1\n  # heterogeneous service's port\n  port: 8060\n\n  # heterogeneous service's health check URL\n  health-check-url: http://localhost:8060/health.json\n```\nNote: `localhost:8060` here, is my local machine started a nginx proxy for this `health.json` request. In actual use it can be any REST service, just need to return the correct JSON format health detection data.\n```json\n\n{\n  \"status\": \"DOWN\"\n}\n```\n\n### Step3: Start Application\nAfter that, start the `Sidecar` service and the local heterogeneous service respectively.\n\nStart in IDE: Find main class  `com.alibaba.cloud.sidecar.DemoApplication`, and execute the main method.\n\nNote: This article takes the `spring-cloud-alibaba-sidecar-nacos-example` project as an example, so it starts the `DemoApplication` startup class under it.\n![idea.png](https://cdn.nlark.com/yuque/0/2022/png/1752280/1662550869316-98d574af-d1ba-4c00-a0af-5e33e13075fd.png)\n\n### Step4: View service registration\n![nacos.png](https://cdn.nlark.com/yuque/0/2022/png/1752280/1662605412601-06780784-915c-40f6-b6b2-67176f6c5419.png)\n\n\n\n\n### Step4: Accessing services\nAfter completing the above 4 steps, we find that the corresponding service `node-service` has been successfully registered to the registry. At this point, the service has been successfully integrated into the Spring Cloud microservice. For Spring Cloud microservices, accessing it is no different than accessing any other Java microservice.\nThis is where the beauty of Spring Cloud Alibaba Sidecar comes in. Next, we will continue to demonstrate how to access this service.\n\nBrowser Access below address:\nhttp://127.0.0.1:8070/node-service/health.json\nIf you see the following message, the access was successful.\n\n![](https://cdn.nlark.com/yuque/0/2022/png/1752280/1662549893322-1b7a761a-ecd7-44ae-88b6-872eca43a866.png)\n\n## More\n\nIf you have any ideas or suggestions for `Spring Cloud Alibaba Sidecar`, please don't hesitate to tell us by submitting github issues.\n\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-consul-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>spring-cloud-alibaba-sidecar-consul-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Sidecar x Consul Example</name>\n    <description>Example demonstrating how to use Spring Cloud Alibaba Sidecar with consul</description>\n    <packaging>jar</packaging>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>com.alibaba.cloud</groupId>\n                    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-consul-discovery</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-consul-example/src/main/java/com/alibaba/cloud/sidecar/DemoApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sidecar;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;\nimport org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;\n\n@SpringBootApplication\n@LoadBalancerClients({\n\t\t@LoadBalancerClient(\"node-service\")\n})\npublic class DemoApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(DemoApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-consul-example/src/main/resources/application.yml",
    "content": "server:\n  port: 8070\nspring:\n  cloud:\n    gateway:\n      discovery:\n        locator:\n          enabled: true\n    consul:\n      host: localhost\n      port: 8500\n  application:\n    name: node-service\nsidecar:\n  # 异构微服务的IP\n  ip: 127.0.0.1\n  # 异构微服务的端口\n  port: 8060\n  # 异构微服务的健康检查URL\n  health-check-url: http://localhost:8060/health.json\nmanagement:\n  endpoint:\n    health:\n      show-details: always"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-nacos-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <version>${revision}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>spring-cloud-alibaba-sidecar-nacos-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Sidecar x Nacos Example</name>\n    <description>Example demonstrating how to use Spring Cloud Alibaba Sidecar with nacos</description>\n    <packaging>jar</packaging>\n\n    <dependencies>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-gateway-server-webflux</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-loadbalancer</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-nacos-example/src/main/java/com/alibaba/cloud/sidecar/DemoApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sidecar;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;\nimport org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;\n\n@SpringBootApplication\n@LoadBalancerClients({\n\t\t@LoadBalancerClient(\"node-service\")\n})\npublic class DemoApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(DemoApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-nacos-example/src/main/resources/application.yml",
    "content": "server:\n  port: 8070\nspring:\n  cloud:\n    nacos:\n      username: 'nacos'\n      password: 'nacos'\n      discovery:\n        server-addr: 127.0.0.1:8848\n        group: test\n    gateway:\n      discovery:\n        locator:\n          enabled: true\n    loadbalancer:\n      nacos:\n        enabled: true\n      ribbon:\n        enabled: false\n\n  application:\n    name: node-service\nsidecar:\n  # 异构微服务的IP\n  ip: 127.0.0.1\n  # 异构微服务的端口\n  port: 8060\n\n  # 异构微服务的健康检查URL\n  #health-check-url: http://localhost:8060/health.json\nmanagement:\n  endpoint:\n    health:\n      show-details: always"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-bus-rocketmq-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <groupId>com.alibaba.cloud</groupId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>spring-cloud-bus-rocketmq-example</artifactId>\n    <name>Spring Cloud Starter Bus Alibaba RocketMQ Example</name>\n    <description>Example demonstrating how to use Spring Cloud Bus RocketMQ</description>\n    <packaging>jar</packaging>\n\n    <dependencies>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-bus-rocketmq</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-bus-rocketmq-example/src/main/java/com/alibaba/cloud/examples/rocketmq/RocketMQBusApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.rocketmq;\n\nimport tools.jackson.databind.ObjectMapper;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.cloud.bus.event.AckRemoteApplicationEvent;\nimport org.springframework.cloud.bus.jackson.RemoteApplicationEventScan;\nimport org.springframework.context.ApplicationEventPublisher;\nimport org.springframework.context.event.EventListener;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * RocketMQ Bus Spring Application.\n *\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n * @since 0.2.1\n */\n@RestController\n@EnableAutoConfiguration\n@RemoteApplicationEventScan(basePackages = \"com.alibaba.cloud.examples.rocketmq\")\npublic class RocketMQBusApplication {\n\n\tpublic static void main(String[] args) {\n\t\tnew SpringApplicationBuilder(RocketMQBusApplication.class)\n\t\t\t\t.properties(\"server.port=0\") // Random server port\n\t\t\t\t.properties(\"management.endpoints.web.exposure.include=*\") // exposure\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// includes\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// all\n\t\t\t\t.properties(\"spring.cloud.bus.trace.enabled=true\") // Enable trace\n\t\t\t\t.run(args);\n\t}\n\n\t@Autowired\n\tprivate ApplicationEventPublisher publisher;\n\n\t@Value(\"${spring.cloud.bus.id}\")\n\tprivate String originService;\n\n\t@Value(\"${server.port}\")\n\tprivate int localServerPort;\n\n\t@Autowired\n\tprivate ObjectMapper objectMapper;\n\n\t/**\n\t * Publish the {@link UserRemoteApplicationEvent}.\n\t * @param name the user name\n\t * @param destination the destination\n\t * @return If published\n\t */\n\t@GetMapping(\"/bus/event/publish/user\")\n\tpublic boolean publish(@RequestParam String name,\n\t\t\t@RequestParam(required = false) String destination) {\n\t\tUser user = new User();\n\t\tuser.setId(System.currentTimeMillis());\n\t\tuser.setName(name);\n\t\tpublisher.publishEvent(\n\t\t\t\tnew UserRemoteApplicationEvent(this, user, originService, destination));\n\t\treturn true;\n\t}\n\n\t/**\n\t * Listener on the {@link UserRemoteApplicationEvent}.\n\t * @param event {@link UserRemoteApplicationEvent}\n\t */\n\t@EventListener\n\tpublic void onEvent(UserRemoteApplicationEvent event) {\n\t\tSystem.out.printf(\"Server [port : %d] listeners on %s\\n\", localServerPort,\n\t\t\t\tevent.getUser());\n\t}\n\n\t@EventListener\n\tpublic void onAckEvent(AckRemoteApplicationEvent event) {\n\t\tSystem.out.printf(\"Server [port : %d] listeners on %s\\n\", localServerPort,\n\t\t\t\tobjectMapper.writeValueAsString(event));\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-bus-rocketmq-example/src/main/java/com/alibaba/cloud/examples/rocketmq/User.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.rocketmq;\n\n/**\n * User Domain.\n *\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n * @since 0.2.1\n */\npublic class User {\n\n\tprivate Long id;\n\n\tprivate String name;\n\n\tpublic Long getId() {\n\t\treturn id;\n\t}\n\n\tpublic void setId(Long id) {\n\t\tthis.id = id;\n\t}\n\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\tpublic void setName(String name) {\n\t\tthis.name = name;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"User{\" + \"id=\" + id + \", name='\" + name + '\\'' + '}';\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-bus-rocketmq-example/src/main/java/com/alibaba/cloud/examples/rocketmq/UserRemoteApplicationEvent.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.examples.rocketmq;\n\nimport org.springframework.cloud.bus.event.RemoteApplicationEvent;\n\n/**\n * {@link User} {@link RemoteApplicationEvent}.\n *\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n * @since 0.2.1\n */\npublic class UserRemoteApplicationEvent extends RemoteApplicationEvent {\n\n\tprivate User user;\n\n\tpublic UserRemoteApplicationEvent() {\n\t}\n\n\tpublic UserRemoteApplicationEvent(Object source, User user, String originService,\n\t\t\tString destinationService) {\n\t\tsuper(source, originService, DEFAULT_DESTINATION_FACTORY.getDestination(originService));\n\t\tthis.user = user;\n\t}\n\n\tpublic void setUser(User user) {\n\t\tthis.user = user;\n\t}\n\n\tpublic User getUser() {\n\t\treturn user;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-bus-rocketmq-example/src/main/resources/application.properties",
    "content": "spring.application.name=spring-cloud-bus-rocketmq-example\nspring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876\nserver.port=8080\nspring.cloud.bus.id=${spring.application.name}:${server.port}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-scheduling-example/README-en.md",
    "content": "# Spring Cloud Alibaba Scheduling Example\n\n## Project description\n\nSpring Cloud Alibaba Scheduling provides a timing task scheduling capability based on Spring Scheduling, supporting distributed scenarios for timing task scheduling. It offers a quick integration solution for timing task scheduling services in distributed scenarios.\n\nThe current offering is based on the open-source ShedLock for distributed lock acquisition, along with Alibaba Cloud's SchedulerX service [quick start](https://sca.aliyun.com/en/docs/2023/user-guide/schedulerx/quick-start/), Subsequent releases will provide access to more open-source solutions implementations.\n\n## Project dependencies\n\n### Access `spring-cloud-starter-alibaba-schedulerx`\n\nAdd the following dependencies to the project `pom.xml`：\n\n   ```xml\n   <dependency>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-starter-alibaba-schedulerx</artifactId>\n   </dependency>\n   ```\n\n## Project config description\n\nIn the Example project, two types of integration configuration modes are provided for `shedlock` and `schedulerx`, Select the required access mode configuration file in `application.yaml`, the example defaults to the shedlock solution.\n\n### Solution 1. Distributed shedlock integration configuration\n\nEdit the following configuration to the `application-schedulerx.yml`:\n   ```yaml\n   spring:\n      cloud:\n         scheduling:\n            # Distributed mode: shedlock, schedulerx\n            # Set config value: shedlock\n            distributed-mode: shedlock\n      datasource:\n         driver-class: com.mysql.cj.jdbc.Driver\n         url: {jdbc_url}\n         username: {jdbc.username}\n         password: {jdbc.password}\n   ```\nYou should replace `{jdbc_url}`,`{jdbc.username}`, and `{jdbc.password}` with your actual database connection information.\n\n>️ Precautions：If there's no database instance can be used, please create a database instance first.\n\n### Solution 2. Alibaba Cloud's SchedulerX integration configuration\nEdit the following configuration to the `application-schedulerx.yml`:\n   ```yaml\n   spring:\n      cloud:\n         scheduling:\n            # Distributed mode: shedlock, schedulerx\n            # Set config value: schedulerx\n            distributed-mode: schedulerx\n            schedulerx:\n               # This configuration is required, Please get it from aliyun schedulerx console\n               endpoint: acm.aliyun.com\n               namespace: aad167f6-xxxx-xxxx-xxxx-xxxxxxxxx\n               groupId: xxxxx\n               appKey: PZm1XXXXXXXXXXXX\n               # Optional config, if you need to sync task to schedulerx\n               # task-sync: true\n               # region-id: public\n               # aliyun-access-key: XXXXXXXXXXXX\n               # aliyun-secret-key: XXXXXXXXXXXX\n               # task-model-default: standalone\n   ```\nOn Alibaba Cloud service, each account has be granted a free quota for schedulerx. For detailed instructions on how to configure and use cloud product integrations, please refer to the respective product documentation. Refer to: [SchedulerX Spring Task](https://www.alibabacloud.com/help/en/schedulerx/user-guide/spring-jobs)\n\n## Start application\n\nAfter completing the above selection and configuration, simply run the `ScheduleApplication` class in Example to start the application. The `SimpleJob` class in this example project includes two Spring scheduled tasks that run every minute. Upon starting, you can expect to see the following logs:\n\n```text\n2024-05-17T11:20:59.981+08:00  INFO 66613 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-17 11:20:59 do job1...\n2024-05-17T11:20:59.985+08:00  INFO 66613 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-1] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-17 11:20:59 do job2...\n```\n### Distributed running verification\n\nCreate two application launch configurations in IDEA, each with the startup parameter `--server.port={port}` to start the corresponding application processes. The example project defaults to using `shedlock`, \nWe can observe that `job1` will be triggered by both applications, whereas `job2` which has been annotated with `@SchedulerLock` will only be triggered in one application at the same time.\n![idea-server-port](images/idea-server-port.png)\n\n- ScheduleApplication-1, startup parameter: `--server.port=18080`, application logs：\n```text\n2024-05-20T14:02:00.003+08:00  INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:02:00 do job1...\n2024-05-20T14:03:00.008+08:00  INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:03:00 do job1...\n2024-05-20T14:03:00.008+08:00  INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-1] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:03:00 do job2...\n2024-05-20T14:04:00.006+08:00  INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-3] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:04:00 do job1...\n2024-05-20T14:04:00.010+08:00  INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-2] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:04:00 do job2...\n2024-05-20T14:05:00.003+08:00  INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-5] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:05:00 do job1...\n```\n- ScheduleApplication-2, startup parameter: `--server.port=18081`, application logs：\n```text\n2024-05-20T14:02:00.003+08:00  INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:02:00 do job1...\n2024-05-20T14:02:00.008+08:00  INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-3] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:02:00 do job2...\n2024-05-20T14:03:00.004+08:00  INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-5] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:03:00 do job1...\n2024-05-20T14:04:00.006+08:00  INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-3] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:04:00 do job1...\n2024-05-20T14:05:00.004+08:00  INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-2] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:05:00 do job1...\n2024-05-20T14:05:00.007+08:00  INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:05:00 do job2...\n```\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-scheduling-example/README.md",
    "content": "# Spring Cloud Alibaba Scheduling Example\n\n## 项目说明\n\nSpring Cloud Alibaba Scheduling 提供了基于 Spring Scheduling 的定时任务调度能力，支持分布式场景下的定时任务调度，为分布式场景下的定时任务调度服务提供快速接入方案。\n\n目前提供基于开源shedlock分布式抢锁模式，以及阿里云上SchedulerX服务的 [快速接入](https://sca.aliyun.com/docs/2023/user-guide/schedulerx/quick-start/) ，后续将提供更多实现的开源方案接入。\n\n## 应用依赖\n\n### 接入 `spring-cloud-starter-alibaba-schedulerx`\n\n在项目 pom.xml 中加入以下依赖：\n\n   ```xml\n   <dependency>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-starter-alibaba-schedulerx</artifactId>\n   </dependency>\n   ```\n\n## 配置说明\n\n在Example工程中提供shedlock和schedulerx的两种接入配置模式（***二选一***），在`application.yaml`中选择需要的接入模式配置文件，案例中默认采用开源的shedlock方案。\n\n### 方案一、分布式shedlock接入配置说明\n\n在 application-schedulerx.yml 配置文件中修改以下配置：\n   ```yaml\n   spring:\n      cloud:\n         scheduling:\n            # Distributed mode: shedlock, schedulerx\n            # Set config value: shedlock\n            distributed-mode: shedlock\n      datasource:\n         driver-class: com.mysql.cj.jdbc.Driver\n         url: {jdbc_url}\n         username: {jdbc.username}\n         password: {jdbc.password}\n   ```\n使用时请需要替换`{jdbc_url}`、`{jdbc.username}`、`{jdbc.password}`为实际自有的数据库连接信息。\n\n>️ 注意：如未创建数据库，请先手动创建数据实例。\n\n### 方案二、云产品SchedulerX接入配置说明\n在 application-schedulerx.yml 配置文件中修改以下配置：\n   ```yaml\n   spring:\n      cloud:\n         scheduling:\n            # Distributed mode: shedlock, schedulerx\n            # Set config value: schedulerx\n            distributed-mode: schedulerx\n            schedulerx:\n               # This configuration is required, Please get it from aliyun schedulerx console\n               endpoint: acm.aliyun.com\n               namespace: aad167f6-xxxx-xxxx-xxxx-xxxxxxxxx\n               groupId: xxxxx\n               appKey: PZm1XXXXXXXXXXXX\n               # Optional config, if you need to sync task to schedulerx\n               # task-sync: true\n               # region-id: public\n               # aliyun-access-key: XXXXXXXXXXXX\n               # aliyun-secret-key: XXXXXXXXXXXX\n               # task-model-default: standalone\n   ```\n阿里云上产品每个用户开通后都会有免费额度，详细云上产品接入配置使用说明，请参考：[阿里云SchedulerX Spring定时任务](https://help.aliyun.com/zh/schedulerx/user-guide/spring-jobs)\n\n## 启动应用\n\n在完成上述接入选择和配置后，直接运行Example中的 `ScheduleApplication`类即可启动运行。本案例工程中的`SimpleJob`类包含了两个每分钟执行一次的Spring定时任务，启动后可得到如下日志：\n```text\n2024-05-17T11:20:59.981+08:00  INFO 66613 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-17 11:20:59 do job1...\n2024-05-17T11:20:59.985+08:00  INFO 66613 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-1] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-17 11:20:59 do job2...\n```\n### 分布式运行验证\n\n在IDEA环境中创建两个应用启动项，各自分别配置启动参数`--server.port={应用端口}`，启动相应的应用进程。案例工程默认采用`shedlock`，\n我们可以直接看到`job1`两个应用都会同时触发，而`job2`添加了`@SchedulerLock`注解则会同一时间点只会在一个应用进程中执行。\n![idea-server-port](images/idea-server-port.png)\n\n- ScheduleApplication-1，启动参数：`--server.port=18080`，定时任务运行日志如下：\n```text\n2024-05-20T14:02:00.003+08:00  INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:02:00 do job1...\n2024-05-20T14:03:00.008+08:00  INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:03:00 do job1...\n2024-05-20T14:03:00.008+08:00  INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-1] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:03:00 do job2...\n2024-05-20T14:04:00.006+08:00  INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-3] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:04:00 do job1...\n2024-05-20T14:04:00.010+08:00  INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-2] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:04:00 do job2...\n2024-05-20T14:05:00.003+08:00  INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-5] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:05:00 do job1...\n```\n- ScheduleApplication-2，启动参数：`--server.port=18081`，定时任务运行日志如下：\n```text\n2024-05-20T14:02:00.003+08:00  INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:02:00 do job1...\n2024-05-20T14:02:00.008+08:00  INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-3] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:02:00 do job2...\n2024-05-20T14:03:00.004+08:00  INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-5] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:03:00 do job1...\n2024-05-20T14:04:00.006+08:00  INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-3] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:04:00 do job1...\n2024-05-20T14:05:00.004+08:00  INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-2] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:05:00 do job1...\n2024-05-20T14:05:00.007+08:00  INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob    : time=2024-05-20 14:05:00 do job2...\n```\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-scheduling-example/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>spring-cloud-alibaba-examples</artifactId>\n        <groupId>com.alibaba.cloud</groupId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>spring-cloud-scheduling-example</artifactId>\n    <name>Spring Cloud Starter Alibaba Scheduling Example</name>\n    <description>Example demonstrating how to use Spring Cloud Schedule</description>\n    <packaging>jar</packaging>\n\n    <dependencies>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-schedulerx</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <!-- database for shedlock start, JDBC data source configuration should be added -->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-jdbc</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.mysql</groupId>\n            <artifactId>mysql-connector-j</artifactId>\n        </dependency>\n        <!-- database for shedlock end -->\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-scheduling-example/src/main/java/com/alibaba/cloud/examples/schedule/ScheduleApplication.java",
    "content": "/*\n * Copyright 2024-present the original author or 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\npackage com.alibaba.cloud.examples.schedule;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.scheduling.annotation.EnableScheduling;\n\n/**\n * ScheduleApplication.\n *\n * @author yaohui\n */\n@SpringBootApplication\n@EnableScheduling\npublic class ScheduleApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(ScheduleApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-scheduling-example/src/main/java/com/alibaba/cloud/examples/schedule/job/SimpleJob.java",
    "content": "/*\n * Copyright 2024-present the original author or 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\npackage com.alibaba.cloud.examples.schedule.job;\n\nimport java.util.concurrent.TimeUnit;\n\nimport net.javacrumbs.shedlock.spring.annotation.SchedulerLock;\nimport org.joda.time.DateTime;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.scheduling.annotation.Scheduled;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author yaohui\n **/\n@Component\npublic class SimpleJob {\n\n\tprivate static final Logger logger = LoggerFactory.getLogger(SimpleJob.class);\n\n\t/**\n\t * run without lock, all instance running at the same time.\n\t */\n\t@Scheduled(cron = \"0 */1 * * * ?\")\n\tpublic void job1() {\n\t\tlogger.info(\"time=\" + DateTime.now().toString(\"YYYY-MM-dd HH:mm:ss\") + \" do job1...\");\n\t}\n\n\n\t/**\n\t * run with lock, only one instance running at the same time.\n\t *\n\t * @throws InterruptedException interrupted exception\n\t */\n\t@Scheduled(cron = \"0 */1 * * * ?\")\n\t@SchedulerLock(name = \"lock-job2\", lockAtMostFor = \"10s\")\n\tpublic void job2() throws InterruptedException {\n\t\tlogger.info(\"time=\" + DateTime.now().toString(\"YYYY-MM-dd HH:mm:ss\") + \" do job2...\");\n\t\tTimeUnit.SECONDS.sleep(1L);\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-scheduling-example/src/main/resources/application-schedulerx.yaml",
    "content": "spring:\n  cloud:\n    scheduling:\n      # Distributed mode: shedlock, schedulerx\n      distributed-mode: schedulerx\n      schedulerx:\n        # This configuration is required, Please get it from aliyun schedulerx console\n        endpoint: acm.aliyun.com\n        namespace: aad167f6-xxxx-xxxx-xxxx-xxxxxxxxx\n        groupId: xxxxx\n        appKey: PZm1XXXXXXXXXXXX\n        # Optional config, if you need to sync task to schedulerx\n#        task-sync: true\n#        region-id: public\n#        aliyun-access-key: XXXXXXXXXXXX\n#        aliyun-secret-key: XXXXXXXXXXXX\n#        task-model-default: standalone\n  autoconfigure:\n    exclude:\n      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-scheduling-example/src/main/resources/application-shedlock.yaml",
    "content": "spring:\n  cloud:\n    scheduling:\n      # Distributed mode: shedlock, schedulerx\n      distributed-mode: shedlock\n  datasource:\n    driver-class: com.mysql.cj.jdbc.Driver\n    # Change to your database jdbc url value\n    url: jdbc:mysql://127.0.0.1:3306/testdb?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true\n    # Change to your database username value\n    username: root\n    # Change to your database password value\n    password: 123456\n"
  },
  {
    "path": "spring-cloud-alibaba-examples/spring-cloud-scheduling-example/src/main/resources/application.yaml",
    "content": "server:\n  port: 18080\nspring:\n  profiles:\n    # Select the config file to use, shedlock or schedulerx\n    active: shedlock\n  application:\n    name: spring-cloud-alibaba-schedule-example\n  # Spring task scheduling config\n  task:\n    scheduling:\n      thread-name-prefix: sca-schedule-\n      pool:\n        size: 5\n      shutdown:\n        await-termination: true\n        await-termination-period: 60s\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <artifactId>spring-cloud-alibaba-starters</artifactId>\n    <packaging>pom</packaging>\n    <name>Spring Cloud Alibaba Starters</name>\n    <description>Spring Cloud Alibaba Starters</description>\n    \n    <modules>\n\n        <module>spring-alibaba-nacos-config</module>\n        <module>spring-cloud-starter-alibaba-nacos-config</module>\n        <module>spring-cloud-starter-alibaba-nacos-discovery</module>\n        <module>spring-cloud-starter-alibaba-seata</module>\n        <module>spring-cloud-starter-stream-rocketmq</module>\n        <module>spring-cloud-starter-bus-rocketmq</module>\n        <module>spring-cloud-starter-alibaba-sidecar</module>\n        <module>spring-cloud-circuitbreaker-sentinel</module>\n        <module>spring-cloud-starter-alibaba-sentinel</module>\n        <module>spring-cloud-alibaba-sentinel-datasource</module>\n        <module>spring-cloud-alibaba-sentinel-gateway</module>\n        <module>spring-cloud-alibaba-commons</module>\n        <module>spring-cloud-starter-alibaba-schedulerx</module>\n    </modules>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.jacoco</groupId>\n                <artifactId>jacoco-maven-plugin</artifactId>\n                <version>${jacoco.version}</version>\n                <executions>\n                    <execution>\n                        <id>jacoco-initialize</id>\n                        <goals>\n                            <goal>prepare-agent</goal>\n                        </goals>\n                    </execution>\n                    <execution>\n                        <id>jacoco-site</id>\n                        <phase>test</phase>\n                        <goals>\n                            <goal>report</goal>\n                        </goals>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-starters</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <artifactId>spring-alibaba-nacos-config</artifactId>\n    <name>Spring Alibaba Nacos Config</name>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-health</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-actuator-autoconfigure</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-configuration-processor</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-client</artifactId>\n        </dependency>\n\n        <!-- Testing -->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>druid</artifactId>\n            <scope>provided</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n    \n        <dependency>\n            <groupId>jakarta.annotation</groupId>\n            <artifactId>jakarta.annotation-api</artifactId>\n        </dependency>\n        \n    </dependencies>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\nimport com.alibaba.cloud.nacos.annotation.NacosAnnotationProcessor;\nimport com.alibaba.cloud.nacos.refresh.NacosContextRefresher;\nimport com.alibaba.cloud.nacos.refresh.NacosRefreshHistory;\n\nimport org.springframework.beans.factory.BeanFactoryUtils;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.autoconfigure.condition.SearchStrategy;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author juven.xuxb\n * @author freeman\n */\n@Configuration(proxyBeanMethods = false)\n@Conditional(NacosConfigEnabledCondition.class)\npublic class NacosConfigAutoConfiguration {\n\n\n\n\t@Bean\n\t@ConditionalOnMissingBean(value = NacosConfigProperties.class, search = SearchStrategy.CURRENT)\n\tpublic NacosConfigProperties nacosConfigProperties(ApplicationContext context) {\n\t\tif (context.getParent() != null && BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context.getParent(),\n\t\t\t\tNacosConfigProperties.class).length > 0) {\n\t\t\treturn BeanFactoryUtils.beanOfTypeIncludingAncestors(context.getParent(), NacosConfigProperties.class);\n\t\t}\n\t\tif (NacosConfigManager.getInstance() == null) { // this should never happen except for some unit tests\n\t\t\treturn new NacosConfigProperties();\n\t\t}\n\t\telse {\n\t\t\treturn NacosConfigManager.getInstance().getNacosConfigProperties();\n\t\t}\n\t}\n\n\t@Bean\n\tpublic NacosRefreshHistory nacosRefreshHistory() {\n\t\treturn new NacosRefreshHistory();\n\t}\n\n\t@Bean\n\tpublic NacosConfigManager nacosConfigManager(NacosConfigProperties nacosConfigProperties) {\n\t\treturn NacosConfigManager.getInstance(nacosConfigProperties);\n\t}\n\n\t@Bean\n\tpublic static NacosAnnotationProcessor nacosAnnotationProcessor() {\n\t\treturn new NacosAnnotationProcessor();\n\t}\n\n\t@Bean\n\tpublic NacosContextRefresher nacosContextRefresher(NacosConfigManager nacosConfigManager,\n\t\t\tNacosRefreshHistory nacosRefreshHistory) {\n\t\t// Consider that it is not necessary to be compatible with the previous\n\t\t// configuration\n\t\t// and use the new configuration if necessary.\n\t\treturn new NacosContextRefresher(nacosConfigManager, nacosRefreshHistory);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigEnabledCondition.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\nimport org.springframework.context.annotation.Condition;\nimport org.springframework.context.annotation.ConditionContext;\nimport org.springframework.core.type.AnnotatedTypeMetadata;\n\n/**\n * @author shiyiyue\n */\npublic class NacosConfigEnabledCondition implements Condition {\n\t@Override\n\tpublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {\n\t\tString prefix = NacosPropertiesPrefixer.getPrefix(context.getEnvironment());\n\t\treturn context.getEnvironment().getProperty(prefix + \".config.enabled\", Boolean.class, true);\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigManager.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\nimport java.util.Objects;\n\nimport com.alibaba.cloud.nacos.diagnostics.analyzer.NacosConnectionFailureException;\nimport com.alibaba.nacos.api.NacosFactory;\nimport com.alibaba.nacos.api.config.ConfigService;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * @author zkzlx\n */\npublic class NacosConfigManager {\n\n\tprivate static final Logger log = LoggerFactory.getLogger(NacosConfigManager.class);\n\n\tprivate static ConfigService service;\n\n\tprivate static NacosConfigManager INSTANCE;\n\n\tprivate NacosConfigProperties nacosConfigProperties;\n\n\tpublic NacosConfigManager(NacosConfigProperties nacosConfigProperties) {\n\t\tthis.nacosConfigProperties = nacosConfigProperties;\n\t}\n\n\tpublic static NacosConfigManager getInstance() {\n\t\treturn INSTANCE;\n\t}\n\n\tpublic static NacosConfigManager getInstance(NacosConfigProperties properties) {\n\t\tif (INSTANCE != null) {\n\t\t\treturn INSTANCE;\n\t\t}\n\t\tsynchronized (NacosConfigManager.class) {\n\t\t\tif (INSTANCE == null) {\n\t\t\t\tINSTANCE = new NacosConfigManager(properties);\n\t\t\t\tINSTANCE.createConfigService(properties);\n\t\t\t}\n\t\t}\n\t\treturn INSTANCE;\n\t}\n\n\t/**\n\t * Compatible with old design,It will be perfected in the future.\n\t */\n\tprivate ConfigService createConfigService(\n\t\t\tNacosConfigProperties nacosConfigProperties) {\n\t\ttry {\n\t\t\tif (Objects.isNull(service)) {\n\t\t\t\tservice = NacosFactory.createConfigService(\n\t\t\t\t\t\tnacosConfigProperties.assembleConfigServiceProperties());\n\t\t\t}\n\t\t}\n\t\tcatch (NacosException e) {\n\t\t\tlog.error(e.getMessage());\n\t\t\tthrow new NacosConnectionFailureException(\n\t\t\t\t\tnacosConfigProperties.getServerAddr(), e.getMessage(), e);\n\t\t}\n\t\treturn service;\n\t}\n\n\tpublic ConfigService getConfigService() {\n\t\tif (Objects.isNull(service)) {\n\t\t\tcreateConfigService(this.nacosConfigProperties);\n\t\t}\n\t\treturn service;\n\t}\n\n\tpublic NacosConfigProperties getNacosConfigProperties() {\n\t\treturn nacosConfigProperties;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Properties;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\nimport com.alibaba.cloud.nacos.utils.PropertySourcesUtils;\nimport com.alibaba.cloud.nacos.utils.StringUtils;\nimport com.alibaba.nacos.api.config.ConfigService;\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport jakarta.annotation.PostConstruct;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.context.properties.DeprecatedConfigurationProperty;\nimport org.springframework.core.env.ConfigurableEnvironment;\nimport org.springframework.core.env.Environment;\n\nimport static com.alibaba.nacos.api.PropertyKeyConst.ACCESS_KEY;\nimport static com.alibaba.nacos.api.PropertyKeyConst.CLUSTER_NAME;\nimport static com.alibaba.nacos.api.PropertyKeyConst.CONFIG_LONG_POLL_TIMEOUT;\nimport static com.alibaba.nacos.api.PropertyKeyConst.CONFIG_RETRY_TIME;\nimport static com.alibaba.nacos.api.PropertyKeyConst.ENABLE_REMOTE_SYNC_CONFIG;\nimport static com.alibaba.nacos.api.PropertyKeyConst.ENCODE;\nimport static com.alibaba.nacos.api.PropertyKeyConst.ENDPOINT;\nimport static com.alibaba.nacos.api.PropertyKeyConst.ENDPOINT_PORT;\nimport static com.alibaba.nacos.api.PropertyKeyConst.MAX_RETRY;\nimport static com.alibaba.nacos.api.PropertyKeyConst.NAMESPACE;\nimport static com.alibaba.nacos.api.PropertyKeyConst.PASSWORD;\nimport static com.alibaba.nacos.api.PropertyKeyConst.RAM_ROLE_NAME;\nimport static com.alibaba.nacos.api.PropertyKeyConst.SECRET_KEY;\nimport static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR;\nimport static com.alibaba.nacos.api.PropertyKeyConst.USERNAME;\n\n/**\n * Nacos properties.\n *\n * @author leijuan\n * @author xiaojing\n * @author pbting\n * @author <a href=\"mailto:lyuzb@lyuzb.com\">lyuzb</a>\n */\npublic class NacosConfigProperties {\n\n\t/**\n\t * COMMAS , .\n\t */\n\tpublic static final String COMMAS = \",\";\n\n\t/**\n\t * SEPARATOR , .\n\t */\n\tpublic static final String SEPARATOR = \"[,]\";\n\n\t/**\n\t * Nacos default namespace .\n\t */\n\tpublic static final String DEFAULT_NAMESPACE = \"public\";\n\n\t/**\n\t * Nacos default server and port.\n\t */\n\tpublic static final String DEFAULT_ADDRESS = \"127.0.0.1:8848\";\n\n\tprivate static final Pattern PATTERN = Pattern.compile(\"-(\\\\w)\");\n\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(NacosConfigProperties.class);\n\n\t@Autowired\n\t@JsonIgnore\n\tprivate Environment environment;\n\t/**\n\t * nacos config server address.\n\t */\n\tprivate String serverAddr;\n\t/**\n\t * the nacos authentication username.\n\t */\n\tprivate String username;\n\t/**\n\t * the nacos authentication password.\n\t */\n\tprivate String password;\n\t/**\n\t * encode for nacos config content.\n\t */\n\tprivate String encode;\n\t/**\n\t * nacos config group, group is config data meta info.\n\t */\n\tprivate String group = \"DEFAULT_GROUP\";\n\t/**\n\t * nacos config dataId prefix.\n\t */\n\tprivate String prefix;\n\t/**\n\t * the suffix of nacos config dataId, also the file extension of config content.\n\t */\n\tprivate String fileExtension = \"properties\";\n\t/**\n\t * timeout for get config from nacos.\n\t */\n\tprivate int timeout = 3000;\n\t/**\n\t * nacos maximum number of tolerable server reconnection errors.\n\t */\n\tprivate String maxRetry;\n\t/**\n\t * nacos get config long poll timeout.\n\t */\n\tprivate String configLongPollTimeout;\n\t/**\n\t * nacos get config failure retry time.\n\t */\n\tprivate String configRetryTime;\n\t/**\n\t * If you want to pull it yourself when the program starts to get the configuration\n\t * for the first time, and the registered Listener is used for future configuration\n\t * updates, you can keep the original code unchanged, just add the system parameter:\n\t * enableRemoteSyncConfig = \"true\" ( But there is network overhead); therefore we\n\t * recommend that you use {@link ConfigService#getConfigAndSignListener} directly.\n\t */\n\tprivate boolean enableRemoteSyncConfig = false;\n\t/**\n\t * endpoint for Nacos, the domain name of a service, through which the server address\n\t * can be dynamically obtained.\n\t */\n\tprivate String endpoint;\n\t/**\n\t * namespace, separation configuration of different environments.\n\t */\n\tprivate String namespace;\n\t/**\n\t * access key for namespace.\n\t */\n\tprivate String accessKey;\n\t/**\n\t * secret key for namespace.\n\t */\n\tprivate String secretKey;\n\t/**\n\t * role name for aliyun ram.\n\t */\n\tprivate String ramRoleName;\n\t/**\n\t * context path for nacos config server.\n\t */\n\tprivate String contextPath;\n\t/**\n\t * nacos config cluster name.\n\t */\n\tprivate String clusterName;\n\t/**\n\t * nacos config dataId name.\n\t */\n\tprivate String name;\n\t/**\n\t * a set of shared configurations .e.g:\n\t * spring.cloud.nacos.config.shared-configs[0]=xxx .\n\t */\n\tprivate List<Config> sharedConfigs;\n\t/**\n\t * a set of extensional configurations .e.g:\n\t * spring.cloud.nacos.config.extension-configs[0]=xxx .\n\t */\n\tprivate List<Config> extensionConfigs;\n\t/**\n\t * the master switch for refresh configuration, it default opened(true).\n\t */\n\tprivate boolean refreshEnabled = true;\n\n\t@PostConstruct\n\tpublic void init() {\n\t\tthis.overrideFromEnv();\n\t}\n\n\tprivate void overrideFromEnv() {\n\t\tif (environment == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tString prefix = NacosPropertiesPrefixer.getPrefix(environment);\n\n\t\tif (StringUtils.isEmpty(this.getServerAddr())) {\n\t\t\tString serverAddr = environment\n\t\t\t\t\t.resolvePlaceholders(\"${\" + prefix + \".config.server-addr:}\");\n\t\t\tif (StringUtils.isEmpty(serverAddr)) {\n\t\t\t\tserverAddr = environment.resolvePlaceholders(\n\t\t\t\t\t\t\"${\" + prefix + \".server-addr:127.0.0.1:8848}\");\n\t\t\t}\n\t\t\tthis.setServerAddr(serverAddr);\n\t\t}\n\t\tif (StringUtils.isEmpty(this.getUsername())) {\n\t\t\tthis.setUsername(\n\t\t\t\t\tenvironment.resolvePlaceholders(\"${\" + prefix + \".username:}\"));\n\t\t}\n\t\tif (StringUtils.isEmpty(this.getPassword())) {\n\t\t\tthis.setPassword(\n\t\t\t\t\tenvironment.resolvePlaceholders(\"${\" + prefix + \".password:}\"));\n\t\t}\n\t}\n\n\t// todo sts support\n\n\tpublic String getServerAddr() {\n\t\treturn serverAddr;\n\t}\n\n\tpublic void setServerAddr(String serverAddr) {\n\t\tthis.serverAddr = serverAddr;\n\t}\n\n\tpublic String getUsername() {\n\t\treturn username;\n\t}\n\n\tpublic void setUsername(String username) {\n\t\tthis.username = username;\n\t}\n\n\tpublic String getPassword() {\n\t\treturn password;\n\t}\n\n\tpublic void setPassword(String password) {\n\t\tthis.password = password;\n\t}\n\n\tpublic String getPrefix() {\n\t\treturn prefix;\n\t}\n\n\tpublic void setPrefix(String prefix) {\n\t\tthis.prefix = prefix;\n\t}\n\n\tpublic String getFileExtension() {\n\t\treturn fileExtension;\n\t}\n\n\tpublic void setFileExtension(String fileExtension) {\n\t\tthis.fileExtension = fileExtension;\n\t}\n\n\tpublic String getGroup() {\n\t\treturn group;\n\t}\n\n\tpublic void setGroup(String group) {\n\t\tthis.group = group;\n\t}\n\n\tpublic int getTimeout() {\n\t\treturn timeout;\n\t}\n\n\tpublic void setTimeout(int timeout) {\n\t\tthis.timeout = timeout;\n\t}\n\n\tpublic String getMaxRetry() {\n\t\treturn maxRetry;\n\t}\n\n\tpublic void setMaxRetry(String maxRetry) {\n\t\tthis.maxRetry = maxRetry;\n\t}\n\n\tpublic String getConfigLongPollTimeout() {\n\t\treturn configLongPollTimeout;\n\t}\n\n\tpublic void setConfigLongPollTimeout(String configLongPollTimeout) {\n\t\tthis.configLongPollTimeout = configLongPollTimeout;\n\t}\n\n\tpublic String getConfigRetryTime() {\n\t\treturn configRetryTime;\n\t}\n\n\tpublic void setConfigRetryTime(String configRetryTime) {\n\t\tthis.configRetryTime = configRetryTime;\n\t}\n\n\tpublic Boolean getEnableRemoteSyncConfig() {\n\t\treturn enableRemoteSyncConfig;\n\t}\n\n\tpublic void setEnableRemoteSyncConfig(Boolean enableRemoteSyncConfig) {\n\t\tthis.enableRemoteSyncConfig = enableRemoteSyncConfig;\n\t}\n\n\tpublic String getEndpoint() {\n\t\treturn endpoint;\n\t}\n\n\tpublic void setEndpoint(String endpoint) {\n\t\tthis.endpoint = endpoint;\n\t}\n\n\tpublic String getNamespace() {\n\t\treturn namespace;\n\t}\n\n\tpublic void setNamespace(String namespace) {\n\t\tthis.namespace = namespace;\n\t}\n\n\tpublic String getAccessKey() {\n\t\treturn accessKey;\n\t}\n\n\tpublic void setAccessKey(String accessKey) {\n\t\tthis.accessKey = accessKey;\n\t}\n\n\tpublic String getSecretKey() {\n\t\treturn secretKey;\n\t}\n\n\tpublic void setSecretKey(String secretKey) {\n\t\tthis.secretKey = secretKey;\n\t}\n\n\tpublic String getRamRoleName() {\n\t\treturn ramRoleName;\n\t}\n\n\tpublic void setRamRoleName(String ramRoleName) {\n\t\tthis.ramRoleName = ramRoleName;\n\t}\n\n\tpublic String getEncode() {\n\t\treturn encode;\n\t}\n\n\tpublic void setEncode(String encode) {\n\t\tthis.encode = encode;\n\t}\n\n\tpublic String getContextPath() {\n\t\treturn contextPath;\n\t}\n\n\tpublic void setContextPath(String contextPath) {\n\t\tthis.contextPath = contextPath;\n\t}\n\n\tpublic String getClusterName() {\n\t\treturn clusterName;\n\t}\n\n\tpublic void setClusterName(String clusterName) {\n\t\tthis.clusterName = clusterName;\n\t}\n\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\tpublic void setName(String name) {\n\t\tthis.name = name;\n\t}\n\n\tpublic Environment getEnvironment() {\n\t\treturn environment;\n\t}\n\n\tpublic void setEnvironment(Environment environment) {\n\t\tthis.environment = environment;\n\t}\n\n\tpublic List<Config> getSharedConfigs() {\n\t\treturn sharedConfigs;\n\t}\n\n\tpublic void setSharedConfigs(List<Config> sharedConfigs) {\n\t\tthis.sharedConfigs = sharedConfigs;\n\t}\n\n\tpublic List<Config> getExtensionConfigs() {\n\t\treturn extensionConfigs;\n\t}\n\n\tpublic void setExtensionConfigs(List<Config> extensionConfigs) {\n\t\tthis.extensionConfigs = extensionConfigs;\n\t}\n\n\tpublic boolean isRefreshEnabled() {\n\t\treturn refreshEnabled;\n\t}\n\n\tpublic void setRefreshEnabled(boolean refreshEnabled) {\n\t\tthis.refreshEnabled = refreshEnabled;\n\t}\n\n\t/**\n\t * recommend to use {@link NacosConfigProperties#sharedConfigs} .\n\t * @return string\n\t */\n\t@Deprecated\n\t@DeprecatedConfigurationProperty(reason = \"use spring.config.import instead\")\n\tpublic String getSharedDataids() {\n\t\treturn null == getSharedConfigs() ? null\n\t\t\t\t: getSharedConfigs().stream().map(Config::getDataId)\n\t\t\t\t.collect(Collectors.joining(COMMAS));\n\t}\n\n\t/**\n\t * recommend to use {@link NacosConfigProperties#sharedConfigs} and not use it at the\n\t * same time .\n\t * @param sharedDataids the dataids for configurable multiple shared configurations ,\n\t *     multiple separated by commas .\n\t */\n\t@Deprecated\n\tpublic void setSharedDataids(String sharedDataids) {\n\t\tif (null != sharedDataids && sharedDataids.trim().length() > 0) {\n\t\t\tList<Config> list = new ArrayList<>();\n\t\t\tStream.of(sharedDataids.split(SEPARATOR))\n\t\t\t\t\t.forEach(dataId -> list.add(new Config(dataId.trim())));\n\t\t\tthis.compatibleSharedConfigs(list);\n\t\t}\n\t}\n\n\t/**\n\t * Not providing support,the need to refresh is specified by the respective refresh\n\t * configuration and not use it at the same time .\n\t * @return string\n\t */\n\t@Deprecated\n\tpublic String getRefreshableDataids() {\n\t\treturn null == getSharedConfigs() ? null\n\t\t\t\t: getSharedConfigs().stream().filter(Config::isRefresh)\n\t\t\t\t.map(Config::getDataId).collect(Collectors.joining(COMMAS));\n\t}\n\n\t/**\n\t * Not providing support,the need to refresh is specified by the respective refresh\n\t * configuration and not use it at the same time .\n\t * @param refreshableDataids refreshable dataids ,multiple separated by commas .\n\t */\n\t@Deprecated\n\tpublic void setRefreshableDataids(String refreshableDataids) {\n\t\tif (null != refreshableDataids && refreshableDataids.trim().length() > 0) {\n\t\t\tList<Config> list = new ArrayList<>();\n\t\t\tStream.of(refreshableDataids.split(SEPARATOR)).forEach(\n\t\t\t\t\tdataId -> list.add(new Config(dataId.trim()).setRefresh(true)));\n\t\t\tthis.compatibleSharedConfigs(list);\n\t\t}\n\t}\n\n\tprivate void compatibleSharedConfigs(List<Config> configList) {\n\t\tif (null != this.getSharedConfigs()) {\n\t\t\tconfigList.addAll(this.getSharedConfigs());\n\t\t}\n\t\tList<Config> result = new ArrayList<>();\n\t\tconfigList.stream()\n\t\t\t\t.collect(Collectors.groupingBy(cfg -> (cfg.getGroup() + cfg.getDataId()),\n\t\t\t\t\t\tLinkedHashMap::new, Collectors.toList()))\n\t\t\t\t.forEach((key, list) -> {\n\t\t\t\t\tlist.stream()\n\t\t\t\t\t\t\t.reduce((a, b) -> new Config(a.getDataId(), a.getGroup(),\n\t\t\t\t\t\t\t\t\ta.isRefresh() || (b != null && b.isRefresh())))\n\t\t\t\t\t\t\t.ifPresent(result::add);\n\t\t\t\t});\n\t\tthis.setSharedConfigs(result);\n\t}\n\n\t/**\n\t * recommend to use\n\t * {@link com.alibaba.cloud.nacos.NacosConfigProperties#extensionConfigs} and not use\n\t * it at the same time .\n\t * @return extensionConfigs\n\t */\n\t@Deprecated\n\t@DeprecatedConfigurationProperty(reason = \"use spring.config.import instead\")\n\tpublic List<Config> getExtConfig() {\n\t\treturn this.getExtensionConfigs();\n\t}\n\n\t@Deprecated\n\tpublic void setExtConfig(List<Config> extConfig) {\n\t\tthis.setExtensionConfigs(extConfig);\n\t}\n\n\t/**\n\t * recommend to use {@link NacosConfigManager#getConfigService()}.\n\t * @return ConfigService\n\t */\n\t@Deprecated\n\tpublic ConfigService configServiceInstance() {\n\t\t// The following code will be migrated\n\t\treturn NacosConfigManager.getInstance(this).getConfigService();\n\t}\n\n\t/**\n\t * recommend to use {@link NacosConfigProperties#assembleConfigServiceProperties()}.\n\t * @return ConfigServiceProperties\n\t */\n\t@Deprecated\n\tpublic Properties getConfigServiceProperties() {\n\t\treturn this.assembleConfigServiceProperties();\n\t}\n\n\t/**\n\t * assemble properties for configService. (cause by rename : Remove the interference\n\t * of auto prompts when writing,because autocue is based on get method.\n\t * @return properties\n\t */\n\tpublic Properties assembleConfigServiceProperties() {\n\t\tProperties properties = new Properties();\n\t\tproperties.put(SERVER_ADDR, Objects.toString(this.serverAddr, \"\"));\n\t\tproperties.put(USERNAME, Objects.toString(this.username, \"\"));\n\t\tproperties.put(PASSWORD, Objects.toString(this.password, \"\"));\n\t\tproperties.put(ENCODE, Objects.toString(this.encode, \"\"));\n\t\tproperties.put(NAMESPACE, this.resolveNamespace());\n\t\tproperties.put(ACCESS_KEY, Objects.toString(this.accessKey, \"\"));\n\t\tproperties.put(SECRET_KEY, Objects.toString(this.secretKey, \"\"));\n\t\tproperties.put(RAM_ROLE_NAME, Objects.toString(this.ramRoleName, \"\"));\n\t\tproperties.put(CLUSTER_NAME, Objects.toString(this.clusterName, \"\"));\n\t\tproperties.put(MAX_RETRY, Objects.toString(this.maxRetry, \"\"));\n\t\tproperties.put(CONFIG_LONG_POLL_TIMEOUT,\n\t\t\t\tObjects.toString(this.configLongPollTimeout, \"\"));\n\t\tproperties.put(CONFIG_RETRY_TIME, Objects.toString(this.configRetryTime, \"\"));\n\t\tproperties.put(ENABLE_REMOTE_SYNC_CONFIG,\n\t\t\t\tObjects.toString(this.enableRemoteSyncConfig, \"\"));\n\t\tString endpoint = Objects.toString(this.endpoint, \"\");\n\t\tif (endpoint.contains(\":\")) {\n\t\t\tint index = endpoint.indexOf(\":\");\n\t\t\tproperties.put(ENDPOINT, endpoint.substring(0, index));\n\t\t\tproperties.put(ENDPOINT_PORT, endpoint.substring(index + 1));\n\t\t}\n\t\telse {\n\t\t\tproperties.put(ENDPOINT, endpoint);\n\t\t}\n\n\t\tenrichNacosConfigProperties(properties);\n\n\t\t// set default value when serverAddr and endpoint is empty\n\t\tif (StringUtils.isEmpty(this.serverAddr) && StringUtils.isEmpty(this.endpoint)) {\n\t\t\tproperties.put(SERVER_ADDR, DEFAULT_ADDRESS);\n\t\t}\n\n\t\treturn properties;\n\t}\n\n\t/**\n\t * refer\n\t * https://github.com/alibaba/spring-cloud-alibaba/issues/2872\n\t * https://github.com/alibaba/spring-cloud-alibaba/issues/2869 .\n\t */\n\tprivate String resolveNamespace() {\n\t\tif (DEFAULT_NAMESPACE.equals(this.namespace)) {\n\t\t\tlog.info(\"set nacos config namespace 'public' to ''\");\n\t\t\treturn \"\";\n\t\t}\n\t\telse {\n\t\t\treturn Objects.toString(this.namespace, \"\");\n\t\t}\n\t}\n\n\tprotected void enrichNacosConfigProperties(Properties nacosConfigProperties) {\n\t\tif (environment == null) {\n\t\t\treturn;\n\t\t}\n\t\tString prefix = NacosPropertiesPrefixer.getPrefix(environment);\n\n\t\tMap<String, Object> properties = PropertySourcesUtils\n\t\t\t\t.getSubProperties((ConfigurableEnvironment) environment, prefix + \".config\");\n\t\tproperties.forEach((k, v) -> nacosConfigProperties.putIfAbsent(resolveKey(k),\n\t\t\t\tString.valueOf(v)));\n\t}\n\n\tprotected String resolveKey(String key) {\n\t\tMatcher matcher = PATTERN.matcher(key);\n\t\tStringBuffer sb = new StringBuffer();\n\t\twhile (matcher.find()) {\n\t\t\tmatcher.appendReplacement(sb, matcher.group(1).toUpperCase(Locale.ROOT));\n\t\t}\n\t\tmatcher.appendTail(sb);\n\t\treturn sb.toString();\n\t}\n\n\t/**\n\t * refer\n\t * https://github.com/alibaba/spring-cloud-alibaba/issues/4242\n\t * Mask sensitive fields in logs to avoid credential leakage.\n\t */\n\tprivate static String mask(String value) {\n\t\treturn (value == null || value.isEmpty()) ? value : \"******\";\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"NacosConfigProperties{\"\n\t\t\t\t+ \"serverAddr='\" + serverAddr + '\\''\n\t\t\t\t+ \", encode='\" + encode + '\\''\n\t\t\t\t+ \", group='\" + group + '\\''\n\t\t\t\t+ \", prefix='\" + prefix + '\\''\n\t\t\t\t+ \", fileExtension='\" + fileExtension + '\\''\n\t\t\t\t+ \", timeout=\" + timeout\n\t\t\t\t+ \", maxRetry='\" + maxRetry + '\\''\n\t\t\t\t+ \", configLongPollTimeout='\" + configLongPollTimeout + '\\''\n\t\t\t\t+ \", configRetryTime='\" + configRetryTime + '\\''\n\t\t\t\t+ \", enableRemoteSyncConfig=\" + enableRemoteSyncConfig\n\t\t\t\t+ \", endpoint='\" + endpoint + '\\''\n\t\t\t\t+ \", namespace='\" + namespace + '\\''\n\t\t\t\t+ \", accessKey='\" + mask(accessKey) + '\\''\n\t\t\t\t+ \", secretKey='\" + mask(secretKey) + '\\''\n\t\t\t\t+ \", ramRoleName='\" + ramRoleName + '\\''\n\t\t\t\t+ \", contextPath='\" + contextPath + '\\''\n\t\t\t\t+ \", clusterName='\" + clusterName + '\\''\n\t\t\t\t+ \", name='\" + name + '\\''\n\t\t\t\t+ \", shares=\" + sharedConfigs\n\t\t\t\t+ \", extensions=\" + extensionConfigs\n\t\t\t\t+ \", refreshEnabled=\" + refreshEnabled\n\t\t\t\t+ '}';\n\t}\n\n\tpublic static class Config {\n\n\t\t/**\n\t\t * the data id of extended configuration.\n\t\t */\n\t\tprivate String dataId;\n\n\t\t/**\n\t\t * the group of extended configuration, the default value is DEFAULT_GROUP.\n\t\t */\n\t\tprivate String group = \"DEFAULT_GROUP\";\n\n\t\t/**\n\t\t * whether to support dynamic refresh, the default does not support .\n\t\t */\n\t\tprivate boolean refresh = false;\n\n\t\tpublic Config() {\n\t\t}\n\n\t\tpublic Config(String dataId) {\n\t\t\tthis.dataId = dataId;\n\t\t}\n\n\t\tpublic Config(String dataId, String group) {\n\t\t\tthis(dataId);\n\t\t\tthis.group = group;\n\t\t}\n\n\t\tpublic Config(String dataId, boolean refresh) {\n\t\t\tthis(dataId);\n\t\t\tthis.refresh = refresh;\n\t\t}\n\n\t\tpublic Config(String dataId, String group, boolean refresh) {\n\t\t\tthis(dataId, group);\n\t\t\tthis.refresh = refresh;\n\t\t}\n\n\t\tpublic String getDataId() {\n\t\t\treturn dataId;\n\t\t}\n\n\t\tpublic Config setDataId(String dataId) {\n\t\t\tthis.dataId = dataId;\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic String getGroup() {\n\t\t\treturn group;\n\t\t}\n\n\t\tpublic Config setGroup(String group) {\n\t\t\tthis.group = group;\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic boolean isRefresh() {\n\t\t\treturn refresh;\n\t\t}\n\n\t\tpublic Config setRefresh(boolean refresh) {\n\t\t\tthis.refresh = refresh;\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn \"Config{\" + \"dataId='\" + dataId + '\\'' + \", group='\" + group + '\\''\n\t\t\t\t\t+ \", refresh=\" + refresh + '}';\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean equals(Object o) {\n\t\t\tif (this == o) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (o == null || getClass() != o.getClass()) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tConfig config = (Config) o;\n\t\t\treturn refresh == config.refresh && Objects.equals(dataId, config.dataId)\n\t\t\t\t\t&& Objects.equals(group, config.group);\n\t\t}\n\n\t\t@Override\n\t\tpublic int hashCode() {\n\t\t\treturn Objects.hash(dataId, group, refresh);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosPropertiesPrefixProvider.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\n/**\n * @author shiyiyue\n */\npublic interface NacosPropertiesPrefixProvider {\n\n\tString getPrefix();\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosPropertiesPrefixer.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\nimport java.util.ServiceLoader;\n\nimport com.alibaba.cloud.nacos.utils.StringUtils;\n\nimport org.springframework.boot.context.properties.bind.BindResult;\nimport org.springframework.boot.context.properties.bind.Binder;\nimport org.springframework.core.env.Environment;\n\n/**\n * @author shiyiyue\n */\npublic final class NacosPropertiesPrefixer {\n\n\t/**\n\t * prefix from spi provider.\n\t */\n\tpublic static final String PREFIX = getPrefixFromSpi();\n\n\tprivate NacosPropertiesPrefixer() {\n\t}\n\n\tprivate static String getPrefixFromSpi() {\n\t\tServiceLoader<NacosPropertiesPrefixProvider> load = ServiceLoader.load(NacosPropertiesPrefixProvider.class);\n\t\tfor (NacosPropertiesPrefixProvider provider : load) {\n\t\t\treturn provider.getPrefix();\n\t\t}\n\t\treturn \"\";\n\t}\n\n\tpublic static String getPrefix(Environment environment) {\n\t\tString prefix = \"spring.nacos\";\n\t\tString prefixFromProperties = environment.getProperty(\"spring.nacos.properties.prefix\");\n\t\tif (StringUtils.isBlank(prefixFromProperties)) {\n\t\t\tif (StringUtils.isNotBlank(NacosPropertiesPrefixer.PREFIX)) {\n\t\t\t\tprefix = NacosPropertiesPrefixer.PREFIX;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tprefix = prefixFromProperties;\n\t\t}\n\n\t\tif (StringUtils.isNotBlank(prefix) && prefix.endsWith(\".\")) {\n\t\t\tprefix = prefix.substring(0, prefix.length() - 1);\n\t\t}\n\t\treturn prefix;\n\t}\n\n\tpublic static String getPrefix(Binder binder) {\n\t\tString prefix = \"spring.nacos\";\n\t\tBindResult<String> bind = binder.bind(\"spring.nacos.properties.prefix\", String.class);\n\t\tif (!bind.isBound()) {\n\t\t\tif (StringUtils.isNotBlank(NacosPropertiesPrefixer.PREFIX)) {\n\t\t\t\tprefix = NacosPropertiesPrefixer.PREFIX;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tprefix = bind.get();\n\t\t}\n\n\t\tif (StringUtils.isNotBlank(prefix) && prefix.endsWith(\".\")) {\n\t\t\tprefix = prefix.substring(0, prefix.length() - 1);\n\t\t}\n\t\treturn prefix;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosPropertySourceRepository.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport com.alibaba.cloud.nacos.client.NacosPropertySource;\n\n/**\n * @author xiaojing\n * @author pbting\n */\npublic final class NacosPropertySourceRepository {\n\n\tprivate final static ConcurrentHashMap<String, NacosPropertySource> NACOS_PROPERTY_SOURCE_REPOSITORY = new ConcurrentHashMap<>();\n\n\tprivate NacosPropertySourceRepository() {\n\n\t}\n\n\t/**\n\t * @return all nacos properties from application context.\n\t */\n\tpublic static List<NacosPropertySource> getAll() {\n\t\treturn new ArrayList<>(NACOS_PROPERTY_SOURCE_REPOSITORY.values());\n\t}\n\n\t/**\n\t * recommend to use {@link NacosPropertySourceRepository#collectNacosPropertySource}.\n\t * @param nacosPropertySource nacosPropertySource\n\t */\n\t@Deprecated\n\tpublic static void collectNacosPropertySources(\n\t\t\tNacosPropertySource nacosPropertySource) {\n\t\tNACOS_PROPERTY_SOURCE_REPOSITORY.putIfAbsent(nacosPropertySource.getDataId(),\n\t\t\t\tnacosPropertySource);\n\t}\n\n\t/**\n\t * recommend to use\n\t * {@link NacosPropertySourceRepository#getNacosPropertySource(java.lang.String, java.lang.String)}.\n\t * @param dataId dataId\n\t * @return NacosPropertySource\n\t */\n\t@Deprecated\n\tpublic static NacosPropertySource getNacosPropertySource(String dataId) {\n\t\treturn NACOS_PROPERTY_SOURCE_REPOSITORY.get(dataId);\n\t}\n\n\tpublic static void collectNacosPropertySource(\n\t\t\tNacosPropertySource nacosPropertySource) {\n\t\tNACOS_PROPERTY_SOURCE_REPOSITORY\n\t\t\t\t.putIfAbsent(getMapKey(nacosPropertySource.getDataId(),\n\t\t\t\t\t\tnacosPropertySource.getGroup()), nacosPropertySource);\n\t}\n\n\tpublic static NacosPropertySource getNacosPropertySource(String dataId,\n\t\t\tString group) {\n\t\treturn NACOS_PROPERTY_SOURCE_REPOSITORY.get(getMapKey(dataId, group));\n\t}\n\n\tpublic static String getMapKey(String dataId, String group) {\n\t\treturn String.join(NacosConfigProperties.COMMAS, String.valueOf(dataId),\n\t\t\t\tString.valueOf(group));\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/annotation/AbstractConfigChangeListener.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.annotation;\n\nimport java.util.Map;\n\nimport com.alibaba.nacos.api.config.ConfigChangeEvent;\nimport com.alibaba.nacos.api.config.ConfigChangeItem;\nimport com.alibaba.nacos.api.config.listener.AbstractSharedListener;\nimport com.alibaba.nacos.client.config.impl.ConfigChangeHandler;\n\npublic abstract class AbstractConfigChangeListener extends AbstractSharedListener implements TargetRefreshable {\n\n\tString lastContent;\n\n\tObject target;\n\n\t@Override\n\tpublic Object getTarget() {\n\t\treturn target;\n\t}\n\n\t@Override\n\tpublic void setTarget(Object target) {\n\t\tthis.target = target;\n\t}\n\n\tpublic AbstractConfigChangeListener(Object target) {\n\t\tthis.target = target;\n\t}\n\n\tprotected void setLastContent(String lastContent) {\n\t\tthis.lastContent = lastContent;\n\t}\n\n\t@Override\n\tpublic void innerReceive(String dataId, String group, String configInfo) {\n\n\t\tMap<String, ConfigChangeItem> data = null;\n\t\ttry {\n\t\t\tdata = ConfigChangeHandler.getInstance().parseChangeData(lastContent, configInfo, type(dataId));\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\tConfigChangeEvent event = new ConfigChangeEvent(data);\n\t\treceiveConfigChange(event);\n\t\tlastContent = configInfo;\n\t}\n\n\tprivate String type(String dataId) {\n\t\tif (dataId.endsWith(\".yml\") || dataId.endsWith(\".yaml\")) {\n\t\t\treturn \"yaml\";\n\t\t}\n\t\treturn \"properties\";\n\t}\n\n\tabstract void receiveConfigChange(ConfigChangeEvent event);\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/annotation/CustomDateDeserializer.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.annotation;\n\nimport java.io.IOException;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\nimport com.fasterxml.jackson.core.JsonParser;\nimport com.fasterxml.jackson.databind.DeserializationContext;\nimport com.fasterxml.jackson.databind.JsonDeserializer;\nimport com.fasterxml.jackson.databind.JsonNode;\n\npublic class CustomDateDeserializer extends JsonDeserializer<Date> {\n\n\tprivate static final long serialVersionUID = 1L;\n\n\tprivate SimpleDateFormat dateFormat = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n\tpublic CustomDateDeserializer() {\n\t\tsuper();\n\t}\n\n\t@Override\n\tpublic Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {\n\t\tJsonNode node = jsonParser.getCodec().readTree(jsonParser);\n\t\tString date = node.textValue();\n\t\ttry {\n\t\t\treturn dateFormat.parse(date);\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new IOException(\"Invalid date format\");\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/annotation/JsonUtils.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.annotation;\n\nimport java.io.IOException;\nimport java.lang.reflect.Type;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosDeserializationException;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.type.TypeFactory;\n\nfinal class JsonUtils {\n\n\tprivate JsonUtils() {\n\t}\n\n\tstatic ObjectMapper mapper = new ObjectMapper();\n\n\tstatic {\n\t\tmapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n\t\tmapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n\t}\n\n\t/**\n\t * Json string deserialize to Object.\n\t *\n\t * @param json json string\n\t * @param cls  class of object\n\t * @param <T>  General type\n\t * @return object\n\t * @throws NacosDeserializationException if deserialize failed\n\t */\n\tpublic static <T> T toObj(String json, Class<T> cls) {\n\t\ttry {\n\t\t\treturn mapper.readValue(json, cls);\n\t\t}\n\t\tcatch (IOException e) {\n\t\t\tthrow new NacosDeserializationException(cls, e);\n\t\t}\n\t}\n\n\tpublic static <T> T toObj(String json, Type type) {\n\t\ttry {\n\t\t\treturn mapper.readValue(json, TypeFactory.defaultInstance().constructType(type));\n\t\t}\n\t\tcatch (IOException e) {\n\t\t\tthrow new NacosDeserializationException(type, e);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/annotation/NacosAnnotationProcessor.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.annotation;\n\nimport java.beans.PropertyDescriptor;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Type;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport com.alibaba.cloud.nacos.NacosConfigManager;\nimport com.alibaba.nacos.api.config.ConfigChangeEvent;\nimport com.alibaba.nacos.api.config.ConfigChangeItem;\nimport com.alibaba.nacos.api.config.listener.AbstractListener;\nimport com.alibaba.nacos.client.config.common.GroupKey;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.BeanUtils;\nimport org.springframework.beans.BeanWrapper;\nimport org.springframework.beans.BeanWrapperImpl;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.NotReadablePropertyException;\nimport org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;\nimport org.springframework.beans.factory.config.BeanDefinition;\nimport org.springframework.beans.factory.config.BeanPostProcessor;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.context.support.GenericApplicationContext;\nimport org.springframework.core.PriorityOrdered;\nimport org.springframework.core.annotation.AnnotationUtils;\nimport org.springframework.core.annotation.MergedAnnotation;\nimport org.springframework.core.annotation.MergedAnnotations;\nimport org.springframework.core.type.MethodMetadata;\nimport org.springframework.util.ReflectionUtils;\n\npublic class NacosAnnotationProcessor implements BeanPostProcessor, PriorityOrdered, ApplicationContextAware {\n\n\tprivate NacosConfigManager nacosConfigManager;\n\n\tprivate ApplicationContext applicationContext;\n\n\tprivate final static Logger log = LoggerFactory\n\t\t\t.getLogger(NacosAnnotationProcessor.class);\n\n\t@Override\n\tpublic int getOrder() {\n\t\treturn 0;\n\t}\n\n\tprivate Map<String, TargetRefreshable> targetListenerMap = new ConcurrentHashMap<>();\n\tprivate Map<String, AtomicReference<String>> groupKeyCache = new ConcurrentHashMap<>();\n\n\tprivate String getGroupKeyContent(String dataId, String group, boolean refreshed) throws Exception {\n\t\tif (groupKeyCache.containsKey(GroupKey.getKey(dataId, group))) {\n\t\t\treturn groupKeyCache.get(GroupKey.getKey(dataId, group)).get();\n\t\t}\n\t\tsynchronized (this) {\n\t\t\tif (!groupKeyCache.containsKey(GroupKey.getKey(dataId, group))) {\n\t\t\t\tString content = getNacosConfigManager().getConfigService().getConfig(dataId, group, 5000);\n\t\t\t\tgroupKeyCache.put(GroupKey.getKey(dataId, group), new AtomicReference<>(content));\n\t\t\t\tif (!refreshed) {\n\t\t\t\t\tlog.info(\"[Nacos Config] refreshed is set to false, not listening config for annotation: dataId={}, group={}\", dataId,\n\t\t\t\t\t\t\tgroup);\n\t\t\t\t\treturn content;\n\t\t\t\t}\n\t\t\t\tlog.info(\"[Nacos Config] Listening config for annotation: dataId={}, group={}\", dataId,\n\t\t\t\t\t\tgroup);\n\t\t\t\tgetNacosConfigManager().getConfigService().addListener(dataId, group, new AbstractListener() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void receiveConfigInfo(String s) {\n\t\t\t\t\t\tgroupKeyCache.get(GroupKey.getKey(dataId, group)).set(s);\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic String toString() {\n\t\t\t\t\t\treturn String.format(\"sca nacos config annotation cache config listener\");\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t}\n\n\t\t\treturn groupKeyCache.get(GroupKey.getKey(dataId, group)).get();\n\t\t}\n\n\t}\n\n\t@Override\n\tpublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {\n\t\tBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);\n\t\treturn bean;\n\t}\n\n\t@Override\n\tpublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {\n\t\tBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);\n\t\tClass clazz = bean.getClass();\n\t\tNacosConfig annotationBean = AnnotationUtils.findAnnotation(clazz, NacosConfig.class);\n\t\tif (annotationBean != null) {\n\t\t\thandleBeanNacosConfigAnnotation(annotationBean.dataId(), annotationBean.group(), annotationBean.key(), annotationBean.refreshed(), beanName, bean, annotationBean.defaultValue());\n\t\t\treturn bean;\n\t\t}\n\n\t\tfor (Field field : getBeanFields(clazz)) {\n\t\t\thandleFiledAnnotation(bean, beanName, field);\n\t\t}\n\t\tfor (Method method : getBeanMethods(clazz)) {\n\t\t\thandleMethodAnnotation(bean, beanName, method);\n\t\t}\n\t\treturn bean;\n\t}\n\n\tprivate List<Field> getBeanFields(Class clazz) {\n\t\tList<Field> res = new ArrayList<>();\n\t\tReflectionUtils.doWithFields(clazz, field -> res.add(field));\n\t\treturn res;\n\t}\n\n\tprivate List<Method> getBeanMethods(Class clazz) {\n\t\tList<Method> res = new ArrayList<>();\n\t\tReflectionUtils.doWithMethods(clazz, method -> res.add(method));\n\t\treturn res;\n\t}\n\n\tprivate void handleFiledAnnotation(Object bean, String beanName, Field field) {\n\t\tNacosConfig annotation = AnnotationUtils.getAnnotation(field, NacosConfig.class);\n\t\tif (annotation != null) {\n\t\t\thandleFiledNacosConfigAnnotation(annotation, beanName, bean, field);\n\t\t}\n\t}\n\n\tprivate void handleBeanNacosConfigAnnotation(String dataId, String group, String key, boolean refreshed, String beanName, Object bean,\n\t\t\tString defaultValue) {\n\t\ttry {\n\t\t\tString config = getDestContent(getGroupKeyContent(dataId, group, refreshed), key);\n\t\t\tif (!org.springframework.util.StringUtils.hasText(config)) {\n\t\t\t\tconfig = defaultValue;\n\t\t\t}\n\n\t\t\t//Init bean properties.\n\t\t\tif (org.springframework.util.StringUtils.hasText(config)) {\n\t\t\t\tObject targetObject = convertContentToTargetType(config, bean.getClass());\n\t\t\t\t//yaml and json to object\n\t\t\t\tBeanUtils.copyProperties(targetObject, bean, getNullPropertyNames(targetObject));\n\t\t\t}\n\n\t\t\tString refreshTargetKey = beanName + \"#instance#\";\n\t\t\tif (!refreshed) {\n\t\t\t\tlog.info(\"[Nacos Config] refresh is set to false,do not register listener for {} to bean {} \", refreshTargetKey, bean);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tTargetRefreshable currentTarget = targetListenerMap.get(refreshTargetKey);\n\t\t\tif (currentTarget != null) {\n\t\t\t\tlog.info(\"[Nacos Config] reset {} listener from  {} to {} \", refreshTargetKey,\n\t\t\t\t\t\tcurrentTarget.getTarget(), bean);\n\t\t\t\ttargetListenerMap.get(refreshTargetKey).setTarget(bean);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlog.info(\"[Nacos Config] register {} listener on {} \", refreshTargetKey,\n\t\t\t\t\tbean);\n\t\t\tTargetRefreshable listener = null;\n\t\t\tif (org.springframework.util.StringUtils.hasText(key)) {\n\t\t\t\tlistener = new NacosPropertiesKeyListener(bean, wrapArrayToSet(key)) {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void configChanged(ConfigChangeEvent event) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tConfigChangeItem changeItem = event.getChangeItem(key);\n\t\t\t\t\t\t\tString newConfig = changeItem == null ? null : changeItem.getNewValue();\n\t\t\t\t\t\t\tif (!org.springframework.util.StringUtils.hasText(newConfig)) {\n\t\t\t\t\t\t\t\tnewConfig = defaultValue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (org.springframework.util.StringUtils.hasText(newConfig)) {\n\t\t\t\t\t\t\t\tObject targetObject = convertContentToTargetType(newConfig, getTarget().getClass());\n\t\t\t\t\t\t\t\t//yaml and json to object\n\t\t\t\t\t\t\t\tBeanUtils.copyProperties(targetObject, getTarget(), getNullPropertyNames(targetObject));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (Exception e) {\n\t\t\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic String toString() {\n\t\t\t\t\t\treturn String.format(\"[spring cloud alibaba nacos config instance key listener , key %s , target %s ] \", key, bean);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlistener = new NacosConfigRefreshableListener(bean) {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void receiveConfigInfo(String configInfo) {\n\t\t\t\t\t\tif (!org.springframework.util.StringUtils.hasText(configInfo)) {\n\t\t\t\t\t\t\tconfigInfo = defaultValue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (org.springframework.util.StringUtils.hasText(configInfo)) {\n\t\t\t\t\t\t\tObject targetObject = convertContentToTargetType(configInfo, bean.getClass());\n\t\t\t\t\t\t\t//yaml and json to object\n\t\t\t\t\t\t\tBeanUtils.copyProperties(targetObject, getTarget(), getNullPropertyNames(targetObject));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic String toString() {\n\t\t\t\t\t\treturn String.format(\"[spring cloud alibaba nacos config instance  listener , key %s , target %s ] \", key, bean);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tgetNacosConfigManager().getConfigService()\n\t\t\t\t\t.addListener(dataId, group, listener);\n\t\t\ttargetListenerMap.put(refreshTargetKey, listener);\n\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\tprivate void handleMethodNacosConfigKeysChangeListener(NacosConfigKeysListener annotation, String beanName, Object bean,\n\t\t\tMethod method) {\n\t\tString dataId = annotation.dataId();\n\t\tString group = annotation.group();\n\t\ttry {\n\t\t\tClass<?>[] parameterTypes = method.getParameterTypes();\n\t\t\tif (parameterTypes.length != 1 || !ConfigChangeEvent.class.isAssignableFrom(parameterTypes[0])) {\n\t\t\t\tthrow new RuntimeException(\n\t\t\t\t\t\t\"NacosConfigKeysChangeListener must be marked as a single parameter with ConfigChangeEvent\");\n\t\t\t}\n\n\t\t\tString refreshTargetKey = beanName + \"#method#\" + methodSignature(method);\n\t\t\tTargetRefreshable currentTarget = targetListenerMap.get(refreshTargetKey);\n\t\t\tif (currentTarget != null) {\n\t\t\t\tlog.info(\"[Nacos Config] reset {} listener from  {} to {} \", refreshTargetKey,\n\t\t\t\t\t\tcurrentTarget.getTarget(), bean);\n\t\t\t\ttargetListenerMap.get(refreshTargetKey).setTarget(bean);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlog.info(\"[Nacos Config] register {} listener on {} \", refreshTargetKey,\n\t\t\t\t\tbean);\n\t\t\t// annotation on string.\n\t\t\tNacosPropertiesKeyListener nacosPropertiesKeyListener = new NacosPropertiesKeyListener(bean, wrapArrayToSet(annotation.interestedKeys()),\n\t\t\t\t\twrapArrayToSet(annotation.interestedKeyPrefixes())) {\n\n\t\t\t\t@Override\n\t\t\t\tpublic void configChanged(ConfigChangeEvent event) {\n\t\t\t\t\tReflectionUtils.invokeMethod(method, this.getTarget(), event);\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic String toString() {\n\t\t\t\t\treturn String.format(\"sca nacos config listener on bean method %s\", bean + \"#\" + methodSignature(method));\n\t\t\t\t}\n\t\t\t};\n\t\t\tnacosPropertiesKeyListener.setLastContent(getGroupKeyContent(dataId, group, true));\n\t\t\tgetNacosConfigManager().getConfigService().addListener(dataId, group,\n\t\t\t\t\tnacosPropertiesKeyListener);\n\t\t\ttargetListenerMap.put(refreshTargetKey, nacosPropertiesKeyListener);\n\t\t}\n\t\tcatch (Throwable e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\tprivate Set<String> wrapArrayToSet(String... arrayKeys) {\n\t\treturn new HashSet<>(Arrays.asList(arrayKeys));\n\t}\n\n\tprivate String methodSignature(Method method) {\n\t\tStringBuilder signature = new StringBuilder(method.getName() + \"(\");\n\t\tClass<?>[] parameterTypes = method.getParameterTypes();\n\t\tfor (int i = 0; i < parameterTypes.length; i++) {\n\t\t\tsignature.append(parameterTypes[i].getSimpleName());\n\t\t\tif (i < parameterTypes.length - 1) {\n\t\t\t\tsignature.append(\", \");\n\t\t\t}\n\t\t}\n\n\t\tsignature.append(\")\");\n\t\treturn signature.toString();\n\t}\n\n\tprivate void handleMethodNacosConfigListener(NacosConfigListener annotation, String beanName, Object bean, Method method) {\n\t\tString dataId = annotation.dataId();\n\t\tString group = annotation.group();\n\t\tString key = annotation.key();\n\t\ttry {\n\t\t\tType[] parameterTypes = method.getGenericParameterTypes();\n\t\t\tif (parameterTypes.length != 1) {\n\t\t\t\tthrow new RuntimeException(\n\t\t\t\t\t\t\"@NacosConfigListener  must be over a method with  a single parameter\");\n\t\t\t}\n\n\t\t\tString configInfo = getGroupKeyContent(dataId, group, true);\n\t\t\tString refreshTargetKey = beanName + \"#method#\" + methodSignature(method);\n\t\t\tTargetRefreshable currentTarget = targetListenerMap.get(refreshTargetKey);\n\t\t\tif (currentTarget != null) {\n\t\t\t\tlog.info(\"[Nacos Config] reset {} listener from  {} to {} \", refreshTargetKey,\n\t\t\t\t\t\tcurrentTarget.getTarget(), bean);\n\t\t\t\ttargetListenerMap.get(refreshTargetKey).setTarget(bean);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlog.info(\"[Nacos Config] register {} listener on {} \", refreshTargetKey,\n\t\t\t\t\tbean);\n\n\t\t\tTargetRefreshable listener = null;\n\t\t\tif (org.springframework.util.StringUtils.hasText(key)) {\n\t\t\t\tlistener = new NacosPropertiesKeyListener(bean, wrapArrayToSet(key)) {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void configChanged(ConfigChangeEvent event) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tConfigChangeItem changeItem = event.getChangeItem(key);\n\t\t\t\t\t\t\tString newConfig = changeItem == null ? null : changeItem.getNewValue();\n\n\t\t\t\t\t\t\tif (org.springframework.util.StringUtils.hasText(newConfig)) {\n\t\t\t\t\t\t\t\tif (invokePrimitiveMethod(method, getTarget(), newConfig)) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tObject targetObject = convertContentToTargetType(newConfig, parameterTypes[0]);\n\t\t\t\t\t\t\t\tReflectionUtils.invokeMethod(method, getTarget(), targetObject);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (Exception e) {\n\t\t\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic String toString() {\n\t\t\t\t\t\treturn String.format(\"[spring cloud alibaba nacos config key listener , key %s , target %s ] \", key, bean + \"#\" + methodSignature(method));\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t((AbstractConfigChangeListener) listener).fillContext(dataId, group);\n\t\t\t\tif (!annotation.initNotify()) {\n\t\t\t\t\t((AbstractConfigChangeListener) listener).setLastContent(configInfo);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlistener = new NacosConfigRefreshableListener(bean) {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void receiveConfigInfo(String configInfo) {\n\t\t\t\t\t\tif (org.springframework.util.StringUtils.hasText(configInfo)) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif (invokePrimitiveMethod(method, getTarget(), configInfo)) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tObject targetObject = convertContentToTargetType(configInfo, parameterTypes[0]);\n\t\t\t\t\t\t\t\tReflectionUtils.invokeMethod(method, getTarget(), targetObject);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcatch (Exception e) {\n\t\t\t\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic String toString() {\n\t\t\t\t\t\treturn String.format(\"[spring cloud alibaba nacos config  listener ,  target %s ] \", bean + \"#\" + methodSignature(method));\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tgetNacosConfigManager().getConfigService().addListener(dataId, group, listener);\n\t\t\ttargetListenerMap.put(refreshTargetKey, listener);\n\t\t\tif (annotation.initNotify() && org.springframework.util.StringUtils.hasText(configInfo)) {\n\t\t\t\ttry {\n\t\t\t\t\tlog.info(\"[Nacos Config] init notify listener of {}  on {} start...\", refreshTargetKey,\n\t\t\t\t\t\t\tbean);\n\t\t\t\t\tlistener.receiveConfigInfo(configInfo);\n\t\t\t\t\tlog.info(\"[Nacos Config] init notify listener of {}  on {} finished \", refreshTargetKey,\n\t\t\t\t\t\t\tbean);\n\t\t\t\t}\n\t\t\t\tcatch (Throwable throwable) {\n\t\t\t\t\tlog.warn(\"[Nacos Config] init notify listener error\", throwable);\n\t\t\t\t\tthrow throwable;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcatch (Throwable e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\n\tObject convertContentToTargetType(String rawContent, Type type) {\n\n\t\tif (String.class.getCanonicalName().equals(type.getTypeName())) {\n\t\t\treturn rawContent;\n\t\t}\n\n\t\tif (Properties.class.getCanonicalName().equals(type.getTypeName())) {\n\t\t\t//properties and yaml config to properties.\n\t\t\tProperties properties = new Properties();\n\t\t\ttry {\n\t\t\t\tif (org.springframework.util.StringUtils.hasText(rawContent)) {\n\t\t\t\t\tproperties = PropertiesUtils.convertToProperties(rawContent);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (Throwable throwable) {\n\t\t\t\tthrow new RuntimeException(throwable);\n\t\t\t}\n\t\t\treturn properties;\n\t\t}\n\t\treturn ObjectUtils.convertToObject(rawContent, type);\n\t}\n\n\tprivate void handleFiledNacosConfigAnnotation(NacosConfig annotation, String beanName, Object bean, Field field) {\n\t\tString dataId = annotation.dataId();\n\t\tString group = annotation.group();\n\t\tString key = annotation.key();\n\t\ttry {\n\t\t\tReflectionUtils.makeAccessible(field);\n\t\t\thandleFiledNacosConfigAnnotationInner(dataId, group, key, annotation.refreshed(), beanName, bean, field, annotation.defaultValue());\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\tprivate void handleFiledNacosConfigAnnotationInner(String dataId, String group, String key, boolean refreshed, String beanName, Object bean,\n\t\t\tField field, String defaultValue) {\n\t\ttry {\n\t\t\tString config = getDestContent(getGroupKeyContent(dataId, group, refreshed), key);\n\t\t\tif (!org.springframework.util.StringUtils.hasText(config)) {\n\t\t\t\tconfig = defaultValue;\n\t\t\t}\n\n\t\t\t//primitive type\n\t\t\tif (handPrimitiveFiled(field, dataId, group, config, key, defaultValue, refreshed, beanName, bean)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t//for other type.\n\t\t\tif (org.springframework.util.StringUtils.hasText(config)) {\n\t\t\t\tObject targetObject = convertContentToTargetType(config, field.getGenericType());\n\t\t\t\t//yaml and json to object\n\t\t\t\tReflectionUtils.setField(field, bean, targetObject);\n\t\t\t}\n\n\t\t\tString refreshTargetKey = beanName + \"#filed#\" + field.getName();\n\n\t\t\tif (!refreshed) {\n\t\t\t\tlog.info(\"[Nacos Config] refresh is set to false,do not register listener for {} to bean {} \", refreshTargetKey, bean);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tTargetRefreshable currentTarget = targetListenerMap.get(refreshTargetKey);\n\t\t\tif (currentTarget != null) {\n\t\t\t\tlog.info(\"[Nacos Config] reset {} listener from  {} to {} \", refreshTargetKey,\n\t\t\t\t\t\tcurrentTarget.getTarget(), bean);\n\t\t\t\ttargetListenerMap.get(refreshTargetKey).setTarget(bean);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlog.info(\"[Nacos Config] register {} listener on {} \", refreshTargetKey,\n\t\t\t\t\tbean);\n\t\t\tTargetRefreshable listener = null;\n\t\t\tif (org.springframework.util.StringUtils.hasText(key)) {\n\t\t\t\tlistener = new NacosPropertiesKeyListener(bean, wrapArrayToSet(key)) {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void configChanged(ConfigChangeEvent event) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tConfigChangeItem changeItem = event.getChangeItem(key);\n\t\t\t\t\t\t\tString newConfig = changeItem == null ? null : changeItem.getNewValue();\n\t\t\t\t\t\t\tif (!org.springframework.util.StringUtils.hasText(newConfig)) {\n\t\t\t\t\t\t\t\tnewConfig = defaultValue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (org.springframework.util.StringUtils.hasText(newConfig)) {\n\t\t\t\t\t\t\t\tObject targetObject = convertContentToTargetType(newConfig, field.getGenericType());\n\t\t\t\t\t\t\t\tReflectionUtils.setField(field, getTarget(), targetObject);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (Exception e) {\n\t\t\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic String toString() {\n\t\t\t\t\t\treturn String.format(\"[spring cloud alibaba nacos config key listener , key %s , target %s ] \", key, bean + \"#\" + field.getName());\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlistener = new NacosConfigRefreshableListener(bean) {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void receiveConfigInfo(String configInfo) {\n\t\t\t\t\t\tif (!org.springframework.util.StringUtils.hasText(configInfo)) {\n\t\t\t\t\t\t\tconfigInfo = defaultValue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (org.springframework.util.StringUtils.hasText(configInfo)) {\n\t\t\t\t\t\t\tObject targetObject = convertContentToTargetType(configInfo, field.getGenericType());\n\t\t\t\t\t\t\tReflectionUtils.setField(field, getTarget(), targetObject);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic String toString() {\n\t\t\t\t\t\treturn String.format(\"[spring cloud alibaba nacos config key listener , key %s , target %s ] \", key, bean + \"#\" + field.getName());\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tgetNacosConfigManager().getConfigService()\n\t\t\t\t\t.addListener(dataId, group, listener);\n\t\t\ttargetListenerMap.put(refreshTargetKey, listener);\n\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\tprivate boolean handPrimitiveFiled(Field field, String dataId, String group, String config, String key, String defaultValue, boolean refreshed, String beanName, Object bean) throws Exception {\n\t\tif (field.getType().isPrimitive()) {\n\n\t\t\tif (org.springframework.util.StringUtils.hasText(config)) {\n\t\t\t\ttry {\n\t\t\t\t\tsetPrimitiveFiled(field, bean, config);\n\t\t\t\t}\n\t\t\t\tcatch (Throwable throwable) {\n\t\t\t\t\tthrow new RuntimeException(throwable);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tString refreshTargetKey = beanName + \"#filed#\" + field.getName();\n\t\t\tif (!refreshed) {\n\t\t\t\tlog.info(\"[Nacos Config] refresh is set to false,do not register listener for {} to bean {} \", refreshTargetKey, bean);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tTargetRefreshable currentTarget = targetListenerMap.get(refreshTargetKey);\n\t\t\tif (currentTarget != null) {\n\t\t\t\tlog.info(\"[Nacos Config] reset {} listener from  {} to {} \", refreshTargetKey,\n\t\t\t\t\t\tcurrentTarget.getTarget(), bean);\n\t\t\t\ttargetListenerMap.get(refreshTargetKey).setTarget(bean);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tlog.info(\"[Nacos Config] register {} listener on {} \", refreshTargetKey,\n\t\t\t\t\tbean);\n\t\t\tTargetRefreshable listener = null;\n\t\t\tif (org.springframework.util.StringUtils.hasText(key)) {\n\t\t\t\tlistener = new NacosPropertiesKeyListener(bean, wrapArrayToSet(key)) {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void configChanged(ConfigChangeEvent event) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tConfigChangeItem changeItem = event.getChangeItem(key);\n\t\t\t\t\t\t\tString newConfig = changeItem == null ? null : changeItem.getNewValue();\n\t\t\t\t\t\t\tif (!org.springframework.util.StringUtils.hasText(newConfig)) {\n\t\t\t\t\t\t\t\tnewConfig = defaultValue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (org.springframework.util.StringUtils.hasText(newConfig)) {\n\t\t\t\t\t\t\t\tsetPrimitiveFiled(field, getTarget(), newConfig);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (Exception e) {\n\t\t\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic String toString() {\n\t\t\t\t\t\treturn String.format(\"[spring cloud alibaba nacos config key listener , key %s , target %s ] \", key, bean + \"#\" + field.getName());\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlistener = new NacosConfigRefreshableListener(bean) {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void receiveConfigInfo(String configInfo) {\n\t\t\t\t\t\tif (!org.springframework.util.StringUtils.hasText(configInfo)) {\n\t\t\t\t\t\t\tconfigInfo = defaultValue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (org.springframework.util.StringUtils.hasText(configInfo)) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tsetPrimitiveFiled(field, getTarget(), configInfo);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcatch (Exception e) {\n\t\t\t\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic String toString() {\n\t\t\t\t\t\treturn String.format(\"[spring cloud alibaba nacos config key listener , key %s , target %s ] \", key, bean + \"#\" + field.getName());\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tgetNacosConfigManager().getConfigService()\n\t\t\t\t\t.addListener(dataId, group, listener);\n\t\t\ttargetListenerMap.put(refreshTargetKey, listener);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate boolean setPrimitiveFiled(Field filed, Object bean, String value) throws Exception {\n\t\tif (filed.getType() == int.class) {\n\t\t\tfiled.setInt(bean, Integer.parseInt(value));\n\t\t}\n\t\telse if (filed.getType() == Integer.class) {\n\t\t\tReflectionUtils.setField(filed, bean, Integer.valueOf(value));\n\t\t}\n\t\telse if (filed.getType() == long.class) {\n\t\t\tfiled.setLong(bean, Long.parseLong(value));\n\t\t}\n\t\telse if (filed.getType() == Long.class) {\n\t\t\tReflectionUtils.setField(filed, bean, Long.valueOf(value));\n\t\t}\n\t\telse if (filed.getType() == boolean.class) {\n\t\t\tfiled.setBoolean(bean, Boolean.parseBoolean(value));\n\t\t}\n\t\telse if (filed.getType() == Boolean.class) {\n\t\t\tReflectionUtils.setField(filed, bean, Boolean.valueOf(value));\n\t\t}\n\t\telse if (filed.getType() == double.class) {\n\t\t\tfiled.setDouble(bean, Double.parseDouble(value));\n\t\t}\n\t\telse if (filed.getType() == Double.class) {\n\t\t\tReflectionUtils.setField(filed, bean, Double.valueOf(value));\n\t\t}\n\t\telse if (filed.getType() == float.class) {\n\t\t\tfiled.setFloat(bean, Float.parseFloat(value));\n\t\t}\n\t\telse if (filed.getType() == Float.class) {\n\t\t\tReflectionUtils.setField(filed, bean, Float.valueOf(value));\n\t\t}\n\t\telse {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\tprivate boolean invokePrimitiveMethod(Method method, Object bean, String value) throws Exception {\n\t\tClass<?> parameterType = method.getParameterTypes()[0];\n\t\tif (parameterType == int.class) {\n\t\t\tReflectionUtils.invokeMethod(method, bean, Integer.parseInt(value));\n\t\t}\n\t\telse if (parameterType == Integer.class) {\n\t\t\tReflectionUtils.invokeMethod(method, bean, Integer.valueOf(value));\n\t\t}\n\t\telse if (parameterType == long.class) {\n\t\t\tReflectionUtils.invokeMethod(method, bean, Long.parseLong(value));\n\t\t}\n\t\telse if (parameterType == Long.class) {\n\t\t\tReflectionUtils.invokeMethod(method, bean, Long.valueOf(value));\n\t\t}\n\t\telse if (parameterType == boolean.class) {\n\t\t\tReflectionUtils.invokeMethod(method, bean, Boolean.parseBoolean(value));\n\t\t}\n\t\telse if (parameterType == Boolean.class) {\n\t\t\tReflectionUtils.invokeMethod(method, bean, Boolean.valueOf(value));\n\t\t}\n\t\telse if (parameterType == double.class) {\n\t\t\tReflectionUtils.invokeMethod(method, bean, Double.parseDouble(value));\n\t\t}\n\t\telse if (parameterType == Double.class) {\n\t\t\tReflectionUtils.invokeMethod(method, bean, Double.valueOf(value));\n\t\t}\n\t\telse if (parameterType == float.class) {\n\t\t\tReflectionUtils.invokeMethod(method, bean, Float.parseFloat(value));\n\t\t}\n\t\telse if (parameterType == Float.class) {\n\t\t\tReflectionUtils.invokeMethod(method, bean, Float.valueOf(value));\n\t\t}\n\t\telse {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\tprivate String getDestContent(String content, String key) throws Exception {\n\t\tif (org.springframework.util.StringUtils.hasText(key)) {\n\t\t\tProperties properties = PropertiesUtils.convertToProperties(content);\n\t\t\treturn properties.getProperty(key);\n\t\t}\n\t\telse {\n\t\t\treturn content;\n\t\t}\n\t}\n\n\tprivate void handleMethodAnnotation(final Object bean, String beanName, final Method method) {\n\t\tNacosConfigKeysListener keysAnnotation = AnnotationUtils.getAnnotation(method, NacosConfigKeysListener.class);\n\t\tif (keysAnnotation != null) {\n\t\t\tReflectionUtils.makeAccessible(method);\n\t\t\thandleMethodNacosConfigKeysChangeListener(keysAnnotation, beanName, bean, method);\n\t\t\treturn;\n\t\t}\n\t\tNacosConfigListener configAnnotation = AnnotationUtils.getAnnotation(method, NacosConfigListener.class);\n\t\tif (configAnnotation != null) {\n\t\t\tReflectionUtils.makeAccessible(method);\n\t\t\thandleMethodNacosConfigListener(configAnnotation, beanName, bean, method);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!applicationContext.containsBeanDefinition(beanName)) {\n\t\t\treturn;\n\t\t}\n\t\tBeanDefinition beanDefinition = ((GenericApplicationContext) applicationContext).getBeanDefinition(beanName);\n\t\tif (beanDefinition instanceof AnnotatedBeanDefinition) {\n\t\t\tMethodMetadata factoryMethodMetadata = (((AnnotatedBeanDefinition) beanDefinition).getFactoryMethodMetadata());\n\t\t\tif (factoryMethodMetadata != null) {\n\n\t\t\t\tMergedAnnotations annotations = factoryMethodMetadata.getAnnotations();\n\t\t\t\tif (annotations != null && annotations.isPresent(NacosConfig.class)) {\n\t\t\t\t\tMergedAnnotation<NacosConfig> nacosConfigMergedAnnotation = annotations.get(NacosConfig.class);\n\t\t\t\t\tMap<String, Object> stringObjectMap = nacosConfigMergedAnnotation.asMap();\n\t\t\t\t\tString dataId = (String) stringObjectMap.get(\"dataId\");\n\n\t\t\t\t\tString group = (String) stringObjectMap.get(\"group\");\n\t\t\t\t\tString key = (String) stringObjectMap.get(\"key\");\n\t\t\t\t\tString defaultValue = (String) stringObjectMap.get(\"defaultValue\");\n\t\t\t\t\thandleBeanNacosConfigAnnotation(dataId, group, key, true, beanName, bean, defaultValue);\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t@Override\n\tpublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n\tprivate NacosConfigManager getNacosConfigManager() {\n\t\tif (this.nacosConfigManager == null) {\n\t\t\tnacosConfigManager = this.applicationContext.getBean(NacosConfigManager.class);\n\n\t\t}\n\t\treturn nacosConfigManager;\n\t}\n\n\tprivate static String[] getNullPropertyNames(Object source) {\n\t\tfinal BeanWrapper src = new BeanWrapperImpl(source);\n\t\tPropertyDescriptor[] pds = src.getPropertyDescriptors();\n\n\t\tSet<String> nullPropertyNames = new HashSet<>();\n\t\tfor (PropertyDescriptor pd : pds) {\n\t\t\tString propertyName = pd.getName();\n\t\t\ttry {\n\t\t\t\tObject propertyValue = src.getPropertyValue(propertyName);\n\t\t\t\tif (propertyValue == null) {\n\t\t\t\t\tnullPropertyNames.add(propertyName);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (NotReadablePropertyException e) {\n\t\t\t\t//ignore\n\t\t\t\tnullPropertyNames.add(propertyName);\n\t\t\t}\n\n\t\t}\n\t\treturn nullPropertyNames.toArray(new String[0]);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/annotation/NacosConfig.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.annotation;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * Nacos Config annotation.\n *\n * @author shiyiyue1102\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})\n@Documented\npublic @interface NacosConfig {\n\n\tString group();\n\n\tString dataId();\n\n\tString key() default \"\";\n\n\tString defaultValue() default \"\";\n\n\tboolean refreshed() default true;\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/annotation/NacosConfigKeysListener.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * @ConfigChangeEvent\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ElementType.METHOD})\npublic @interface NacosConfigKeysListener {\n\n\tString dataId();\n\n\tString group();\n\n\tString[] interestedKeys() default {};\n\n\tString[] interestedKeyPrefixes() default {};\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/annotation/NacosConfigListener.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ElementType.METHOD})\npublic @interface NacosConfigListener {\n\n\tString dataId();\n\n\tString group();\n\n\tString key() default \"\";\n\n\tboolean initNotify() default false;\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/annotation/NacosConfigRefreshableListener.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.annotation;\n\nimport com.alibaba.nacos.api.config.listener.AbstractListener;\n\npublic abstract class NacosConfigRefreshableListener extends AbstractListener implements TargetRefreshable {\n\n\tObject target;\n\n\tNacosConfigRefreshableListener(Object target) {\n\t\tthis.target = target;\n\t}\n\n\tpublic Object getTarget() {\n\t\treturn target;\n\t}\n\n\t@Override\n\tpublic void setTarget(Object target) {\n\t\tthis.target = target;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/annotation/NacosPropertiesKeyListener.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.annotation;\n\nimport java.util.Set;\n\nimport com.alibaba.nacos.api.config.ConfigChangeEvent;\nimport com.alibaba.nacos.api.config.ConfigChangeItem;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\n\npublic abstract class NacosPropertiesKeyListener extends AbstractConfigChangeListener {\n\n\tSet<String> interestedKeys;\n\n\tSet<String> interestedKeyPrefixes;\n\n\tNacosPropertiesKeyListener(Object target) {\n\t\tsuper(target);\n\t}\n\n\tNacosPropertiesKeyListener(Object target, Set<String> interestedKeys) {\n\t\tthis(target);\n\t\tthis.interestedKeys = interestedKeys;\n\t}\n\n\tpublic NacosPropertiesKeyListener(Object target, Set<String> interestedKeys, Set<String> interestedKeyPrefixes) {\n\t\tthis(target);\n\t\tthis.interestedKeys = interestedKeys;\n\t\tthis.interestedKeyPrefixes = interestedKeyPrefixes;\n\t}\n\n\t@Override\n\tpublic final void receiveConfigChange(ConfigChangeEvent event) {\n\t\tif (CollectionUtils.isNotEmpty(interestedKeys) || CollectionUtils.isNotEmpty(interestedKeyPrefixes)) {\n\t\t\tboolean foundInterested = false;\n\t\t\tfor (ConfigChangeItem changeItem : event.getChangeItems()) {\n\t\t\t\tif (interestedKeys != null && matchesInterestedKey(changeItem.getKey(), interestedKeys)) {\n\t\t\t\t\tfoundInterested = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (interestedKeyPrefixes != null) {\n\t\t\t\t\tfor (String prefix : interestedKeyPrefixes) {\n\t\t\t\t\t\tif (changeItem.getKey().startsWith(prefix)) {\n\t\t\t\t\t\t\tfoundInterested = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!foundInterested) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tconfigChanged(event);\n\t}\n\n\t/**\n\t * Check whether the changed key matches any of the interested keys.\n\t *\n\t * For YAML array/list configurations, the config change parser flattens keys\n\t * with array indices (e.g. {@code myList[0]}, {@code myList[1]}), but users\n\t * typically register interest in the base key ({@code myList}). This method\n\t * handles both exact matches and array-indexed key matches by stripping the\n\t * first {@code [index]} suffix and checking against the interested keys.\n\t *\n\t * @param changedKey the key from the {@link ConfigChangeItem}\n\t * @param interestedKeys the set of keys the listener is interested in\n\t * @return {@code true} if the changed key matches any interested key\n\t */\n\tprivate boolean matchesInterestedKey(String changedKey, Set<String> interestedKeys) {\n\t\tif (interestedKeys.contains(changedKey)) {\n\t\t\treturn true;\n\t\t}\n\t\t// Handle array-indexed keys: \"key[0]\" or \"key[0].nested\" should match \"key\"\n\t\tint bracketIndex = changedKey.indexOf('[');\n\t\tif (bracketIndex > 0) {\n\t\t\tString baseKey = changedKey.substring(0, bracketIndex);\n\t\t\treturn interestedKeys.contains(baseKey);\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"NacosPropertiesKeyListener{\" + \"interestedKeys=\" + interestedKeys + \", interestedKeyPrefixes=\"\n\t\t\t\t+ interestedKeyPrefixes + '}' + \"@\" + hashCode();\n\t}\n\n\tpublic abstract void configChanged(ConfigChangeEvent event);\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/annotation/ObjectUtils.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.annotation;\n\nimport java.lang.reflect.Type;\n\nimport org.springframework.util.StringUtils;\n\nfinal class ObjectUtils {\n\n\tprivate ObjectUtils() {\n\t}\n\n\tpublic static Object convertToObject(String content, Type clazz) {\n\t\tif (!StringUtils.hasText(content)) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn convertFormJsonContent(content, clazz);\n\t}\n\n\tprivate static Object convertFormJsonContent(String content, Type clazz) {\n\n\t\treturn JsonUtils.toObj(content, clazz);\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/annotation/PropertiesUtils.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.annotation;\n\nimport java.io.StringReader;\nimport java.util.Map;\nimport java.util.Properties;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.yaml.snakeyaml.LoaderOptions;\nimport org.yaml.snakeyaml.Yaml;\nimport org.yaml.snakeyaml.constructor.SafeConstructor;\n\nfinal class PropertiesUtils {\n\n\tprivate PropertiesUtils() {\n\t}\n\n\tpublic static Properties convertToProperties(String content) throws Exception {\n\t\tif (StringUtils.isBlank(content)) {\n\t\t\treturn new Properties();\n\t\t}\n\t\ttry {\n\t\t\treturn convertFormYamlContent(content);\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\treturn convertFormPropertiesContent(content);\n\t\t}\n\t}\n\n\tprivate static Properties convertFormPropertiesContent(String content) throws Exception {\n\t\tProperties properties = new Properties();\n\t\tproperties.load(new StringReader(content));\n\t\treturn properties;\n\t}\n\n\tprivate static Properties convertFormYamlContent(String content) {\n\n\t\tYaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));\n\t\tMap<String, Object> yamlMap = yaml.load(content);\n\n\t\tProperties properties = new Properties();\n\t\tflattenMap(\"\", yamlMap, properties);\n\n\t\treturn properties;\n\t}\n\n\tprivate static void flattenMap(String prefix, Map<String, Object> map, Properties properties) {\n\t\tfor (Map.Entry<String, Object> entry : map.entrySet()) {\n\t\t\tString key =\n\t\t\t\t\tprefix.isEmpty() ? String.valueOf(entry.getKey()) : prefix + \".\" + String.valueOf(entry.getKey());\n\t\t\tif (entry.getValue() instanceof Map) {\n\t\t\t\tflattenMap(key, (Map<String, Object>) entry.getValue(), properties);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tproperties.setProperty(key, entry.getValue().toString());\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/annotation/ScaYamlConfigChangeParser.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.annotation;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Iterator;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\nimport com.alibaba.nacos.api.config.ConfigChangeItem;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.client.config.impl.YmlChangeParser;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.yaml.snakeyaml.LoaderOptions;\nimport org.yaml.snakeyaml.Yaml;\nimport org.yaml.snakeyaml.composer.ComposerException;\nimport org.yaml.snakeyaml.constructor.SafeConstructor;\nimport org.yaml.snakeyaml.error.MarkedYAMLException;\n\npublic class ScaYamlConfigChangeParser extends YmlChangeParser {\n\tprivate static final String INVALID_CONSTRUCTOR_ERROR_INFO = \"could not determine a constructor for the tag\";\n\n\tpublic ScaYamlConfigChangeParser() {\n\t\tsuper();\n\t}\n\n\t@Override\n\tpublic Map<String, ConfigChangeItem> doParse(String oldContent, String newContent, String type) {\n\t\tMap<String, Object> oldMap = Collections.emptyMap();\n\t\tMap<String, Object> newMap = Collections.emptyMap();\n\t\ttry {\n\t\t\tYaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));\n\t\t\tif (StringUtils.isNotBlank(oldContent)) {\n\t\t\t\toldMap = yaml.load(oldContent);\n\t\t\t\toldMap = getFlattenedMap(oldMap);\n\t\t\t}\n\t\t\tif (StringUtils.isNotBlank(newContent)) {\n\t\t\t\tnewMap = yaml.load(newContent);\n\t\t\t\tnewMap = getFlattenedMap(newMap);\n\t\t\t}\n\t\t}\n\t\tcatch (MarkedYAMLException e) {\n\t\t\thandleYamlException(e);\n\t\t}\n\n\t\treturn filterChangeData(oldMap, newMap);\n\t}\n\n\tprivate void handleYamlException(MarkedYAMLException e) {\n\t\tif (e.getMessage().startsWith(INVALID_CONSTRUCTOR_ERROR_INFO) || e instanceof ComposerException) {\n\t\t\tthrow new NacosRuntimeException(NacosException.INVALID_PARAM,\n\t\t\t\t\t\"AbstractConfigChangeListener only support basic java data type for yaml. If you want to listen \"\n\t\t\t\t\t\t\t+ \"key changes for custom classes, please use `Listener` to listener whole yaml configuration and parse it by yourself.\",\n\t\t\t\t\te);\n\t\t}\n\t\tthrow e;\n\t}\n\n\tprivate Map<String, Object> getFlattenedMap(Map<String, Object> source) {\n\t\tMap<String, Object> result = new LinkedHashMap<>(128);\n\t\tbuildFlattenedMap(result, source, null);\n\t\treturn result;\n\t}\n\n\tprivate void buildFlattenedMap(Map<String, Object> result, Map<String, Object> source, String path) {\n\t\tfor (Iterator<Map.Entry<String, Object>> itr = source.entrySet().iterator(); itr.hasNext(); ) {\n\t\t\tMap.Entry<String, Object> e = itr.next();\n\t\t\tString key = String.valueOf(e.getKey());\n\t\t\tif (StringUtils.isNotBlank(path)) {\n\t\t\t\tif (key.startsWith(\"[\")) {\n\t\t\t\t\tkey = path + key;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tkey = path + '.' + key;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (e.getValue() instanceof String) {\n\t\t\t\tresult.put(key, e.getValue());\n\t\t\t}\n\t\t\telse if (e.getValue() instanceof Map) {\n\t\t\t\t@SuppressWarnings(\"unchecked\") Map<String, Object> map = (Map<String, Object>) e.getValue();\n\t\t\t\tbuildFlattenedMap(result, map, key);\n\t\t\t}\n\t\t\telse if (e.getValue() instanceof Collection) {\n\t\t\t\t@SuppressWarnings(\"unchecked\") Collection<Object> collection = (Collection<Object>) e.getValue();\n\t\t\t\tif (collection.isEmpty()) {\n\t\t\t\t\tresult.put(key, \"\");\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tint count = 0;\n\t\t\t\t\tfor (Object object : collection) {\n\t\t\t\t\t\tbuildFlattenedMap(result, Collections.singletonMap(\"[\" + (count++) + \"]\", object), key);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tresult.put(key, (e.getValue() != null ? e.getValue() : \"\"));\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/annotation/TargetRefreshable.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.annotation;\n\nimport com.alibaba.nacos.api.config.listener.Listener;\n\ninterface TargetRefreshable extends Listener {\n\n\tObject getTarget();\n\n\tvoid setTarget(Object target);\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySource.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.client;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.alibaba.cloud.nacos.NacosConfigProperties;\n\nimport org.springframework.core.env.MapPropertySource;\nimport org.springframework.core.env.PropertySource;\nimport org.springframework.util.CollectionUtils;\n\n/**\n * @author xiaojing\n * @author pbting\n */\npublic class NacosPropertySource extends MapPropertySource {\n\n\t/**\n\t * Nacos Group.\n\t */\n\tprivate final String group;\n\n\t/**\n\t * Nacos dataID.\n\t */\n\tprivate final String dataId;\n\n\t/**\n\t * timestamp the property get.\n\t */\n\tprivate final Date timestamp;\n\n\t/**\n\t * Whether to support dynamic refresh for this Property Source.\n\t */\n\tprivate final boolean isRefreshable;\n\n\tNacosPropertySource(String group, String dataId, Map<String, Object> source,\n\t\t\tDate timestamp, boolean isRefreshable) {\n\t\tsuper(String.join(NacosConfigProperties.COMMAS, dataId, group), source);\n\t\tthis.group = group;\n\t\tthis.dataId = dataId;\n\t\tthis.timestamp = timestamp;\n\t\tthis.isRefreshable = isRefreshable;\n\t}\n\n\tpublic NacosPropertySource(List<PropertySource<?>> propertySources, String group,\n\t\t\tString dataId, Date timestamp, boolean isRefreshable) {\n\t\tthis(group, dataId, getSourceMap(group, dataId, propertySources), timestamp,\n\t\t\t\tisRefreshable);\n\t}\n\n\tprivate static Map<String, Object> getSourceMap(String group, String dataId,\n\t\t\tList<PropertySource<?>> propertySources) {\n\t\tif (CollectionUtils.isEmpty(propertySources)) {\n\t\t\treturn Collections.emptyMap();\n\t\t}\n\t\t// If only one, return the internal element, otherwise wrap it.\n\t\tif (propertySources.size() == 1) {\n\t\t\tPropertySource propertySource = propertySources.get(0);\n\t\t\tif (propertySource != null && propertySource.getSource() instanceof Map source) {\n\t\t\t\treturn source;\n\t\t\t}\n\t\t}\n\n\t\tMap<String, Object> sourceMap = new LinkedHashMap<>();\n\t\tList<PropertySource<?>> otherTypePropertySources = new ArrayList<>();\n\t\tfor (PropertySource<?> propertySource : propertySources) {\n\t\t\tif (propertySource == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (propertySource instanceof MapPropertySource mapPropertySource) {\n\t\t\t\t// If the Nacos configuration file uses \"---\" to separate property name,\n\t\t\t\t// propertySources will be multiple documents, and every document is a\n\t\t\t\t// map.\n\t\t\t\t// see org.springframework.boot.env.YamlPropertySourceLoader#load\n\t\t\t\tMap<String, Object> source = mapPropertySource.getSource();\n\t\t\t\tsourceMap.putAll(source);\n\t\t\t}\n\t\t\telse {\n\t\t\t\totherTypePropertySources.add(propertySource);\n\t\t\t}\n\t\t}\n\n\t\t// Other property sources which is not instanceof MapPropertySource will be put as\n\t\t// it is,\n\t\t// and the internal elements cannot be directly retrieved,\n\t\t// so the user needs to implement the retrieval logic by himself\n\t\tif (!otherTypePropertySources.isEmpty()) {\n\t\t\tsourceMap.put(String.join(NacosConfigProperties.COMMAS, dataId, group),\n\t\t\t\t\totherTypePropertySources);\n\t\t}\n\t\treturn sourceMap;\n\t}\n\n\tpublic String getGroup() {\n\t\treturn this.group;\n\t}\n\n\tpublic String getDataId() {\n\t\treturn dataId;\n\t}\n\n\tpublic Date getTimestamp() {\n\t\treturn timestamp;\n\t}\n\n\tpublic boolean isRefreshable() {\n\t\treturn isRefreshable;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceBuilder.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.client;\n\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.List;\n\nimport com.alibaba.cloud.nacos.NacosPropertySourceRepository;\nimport com.alibaba.cloud.nacos.parser.NacosDataParserHandler;\nimport com.alibaba.cloud.nacos.refresh.NacosSnapshotConfigManager;\nimport com.alibaba.cloud.nacos.utils.StringUtils;\nimport com.alibaba.nacos.api.config.ConfigService;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.core.env.PropertySource;\n\n/**\n * @author xiaojing\n * @author pbting\n */\npublic class NacosPropertySourceBuilder {\n\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(NacosPropertySourceBuilder.class);\n\n\tprivate ConfigService configService;\n\n\tprivate long timeout;\n\n\tpublic NacosPropertySourceBuilder(ConfigService configService, long timeout) {\n\t\tthis.configService = configService;\n\t\tthis.timeout = timeout;\n\t}\n\n\tpublic long getTimeout() {\n\t\treturn timeout;\n\t}\n\n\tpublic void setTimeout(long timeout) {\n\t\tthis.timeout = timeout;\n\t}\n\n\tpublic ConfigService getConfigService() {\n\t\treturn configService;\n\t}\n\n\tpublic void setConfigService(ConfigService configService) {\n\t\tthis.configService = configService;\n\t}\n\n\t/**\n\t * @param dataId Nacos dataId\n\t * @param group Nacos group\n\t */\n\tpublic NacosPropertySource build(String dataId, String group, String fileExtension,\n\t\t\tboolean isRefreshable) {\n\t\tList<PropertySource<?>> propertySources = loadNacosData(dataId, group,\n\t\t\t\tfileExtension);\n\t\tNacosPropertySource nacosPropertySource = new NacosPropertySource(propertySources,\n\t\t\t\tgroup, dataId, new Date(), isRefreshable);\n\t\tNacosPropertySourceRepository.collectNacosPropertySource(nacosPropertySource);\n\t\treturn nacosPropertySource;\n\t}\n\n\tprivate List<PropertySource<?>> loadNacosData(String dataId, String group,\n\t\t\tString fileExtension) {\n\t\tString data = null;\n\t\ttry {\n\t\t\tString configSnapshot = NacosSnapshotConfigManager.getAndRemoveConfigSnapshot(dataId, group);\n\t\t\tif (StringUtils.isEmpty(configSnapshot)) {\n\t\t\t\tlog.debug(\"get config from nacos, dataId: {}, group: {}\", dataId, group);\n\t\t\t\tdata = configService.getConfig(dataId, group, timeout);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlog.debug(\"get config from memory snapshot, dataId: {}, group: {}\",\n\t\t\t\t\t\tdataId, group);\n\t\t\t\tdata = configSnapshot;\n\t\t\t}\n\t\t\tif (StringUtils.isEmpty(data)) {\n\t\t\t\tlog.warn(\n\t\t\t\t\t\t\"Ignore the empty nacos configuration and get it based on dataId[{}] & group[{}]\",\n\t\t\t\t\t\tdataId, group);\n\t\t\t\treturn Collections.emptyList();\n\t\t\t}\n\t\t\tif (log.isDebugEnabled()) {\n\t\t\t\tlog.debug(String.format(\n\t\t\t\t\t\t\"Loading nacos data, dataId: '%s', group: '%s', data: %s\", dataId,\n\t\t\t\t\t\tgroup, data));\n\t\t\t}\n\t\t\treturn NacosDataParserHandler.getInstance().parseNacosData(dataId, data,\n\t\t\t\t\tfileExtension);\n\t\t}\n\t\tcatch (NacosException e) {\n\t\t\tlog.error(\"get data from Nacos error,dataId:{} \", dataId, e);\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tlog.error(\"parse data from Nacos error,dataId:{},data:{}\", dataId, data, e);\n\t\t}\n\t\treturn Collections.emptyList();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/configdata/ConfigPreference.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.configdata;\n\n/**\n * Config preference.\n * <p>\n * When configured profile specific configuration, local config will override the remote,\n * because the local config is <strong>profile specific</strong>, it has higher priority.\n * <p>\n * So give remote config a chance to \"win\", we treat remote config as profile specific, it\n * should be included after profile specific sibling imports. Eventually, it will override\n * the local profile specific config.\n *\n * @author freeman\n * @since 2021.0.4.0\n */\npublic enum ConfigPreference {\n\t/**\n\t * Prefer local configuration.\n\t */\n\tLOCAL,\n\t/**\n\t * Prefer remote configuration.\n\t */\n\tREMOTE\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataLoadProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.configdata;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\nimport com.alibaba.cloud.nacos.NacosConfigProperties;\n\n/**\n * Used for initialization of Nacos ConfigService.\n */\npublic class NacosConfigDataLoadProperties extends NacosConfigProperties {\n\tprivate Map<String, String> config = new HashMap<>();\n\n\t@Override\n\tprotected void enrichNacosConfigProperties(Properties nacosConfigProperties) {\n\t\tconfig.forEach((k, v) -> nacosConfigProperties.putIfAbsent(resolveKey(k),\n\t\t\t\tString.valueOf(v)));\n\t}\n\n\tMap<String, String> getConfig() {\n\t\treturn config;\n\t}\n\n\tvoid setConfig(Map<String, String> config) {\n\t\tthis.config = config;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataLoader.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.configdata;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Locale;\n\nimport com.alibaba.cloud.nacos.NacosConfigManager;\nimport com.alibaba.cloud.nacos.NacosConfigProperties;\nimport com.alibaba.cloud.nacos.NacosPropertiesPrefixer;\nimport com.alibaba.cloud.nacos.NacosPropertySourceRepository;\nimport com.alibaba.cloud.nacos.client.NacosPropertySource;\nimport com.alibaba.cloud.nacos.parser.NacosDataParserHandler;\nimport com.alibaba.nacos.api.config.ConfigService;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.apache.commons.logging.Log;\n\nimport org.springframework.boot.context.config.ConfigData;\nimport org.springframework.boot.context.config.ConfigDataLoader;\nimport org.springframework.boot.context.config.ConfigDataLoaderContext;\nimport org.springframework.boot.context.config.ConfigDataResourceNotFoundException;\nimport org.springframework.boot.context.properties.bind.Binder;\nimport org.springframework.boot.logging.DeferredLogFactory;\nimport org.springframework.core.env.PropertySource;\n\nimport static com.alibaba.cloud.nacos.configdata.ConfigPreference.LOCAL;\nimport static com.alibaba.cloud.nacos.configdata.ConfigPreference.REMOTE;\nimport static com.alibaba.cloud.nacos.configdata.NacosConfigDataResource.NacosItemConfig;\nimport static org.springframework.boot.context.config.ConfigData.Option;\n\n/**\n * Implementation of {@link ConfigDataLoader}.\n *\n * <p>\n * Load {@link ConfigData} via {@link NacosConfigDataResource}\n *\n * @author freeman\n * @since 2021.0.1.0\n */\npublic class NacosConfigDataLoader implements ConfigDataLoader<NacosConfigDataResource> {\n\n\tprivate final Log log;\n\n\tpublic NacosConfigDataLoader(DeferredLogFactory logFactory) {\n\t\tthis.log = logFactory.getLog(getClass());\n\t}\n\n\t@Override\n\tpublic ConfigData load(ConfigDataLoaderContext context,\n\t\t\tNacosConfigDataResource resource) {\n\t\treturn doLoad(context, resource);\n\t}\n\n\tpublic ConfigData doLoad(ConfigDataLoaderContext context,\n\t\t\tNacosConfigDataResource resource) {\n\t\ttry {\n\t\t\tConfigService configService = getBean(context, NacosConfigManager.class)\n\t\t\t\t\t.getConfigService();\n\t\t\tNacosConfigProperties properties = getBean(context,\n\t\t\t\t\tNacosConfigProperties.class);\n\n\t\t\tNacosItemConfig config = resource.getConfig();\n\t\t\t// pull config from nacos\n\t\t\tList<PropertySource<?>> propertySources = pullConfig(configService,\n\t\t\t\t\tconfig.getGroup(), config.getDataId(), config.getSuffix(),\n\t\t\t\t\tproperties.getTimeout());\n\n\t\t\tNacosPropertySource propertySource = new NacosPropertySource(propertySources,\n\t\t\t\t\tconfig.getGroup(), config.getDataId(), new Date(),\n\t\t\t\t\tconfig.isRefreshEnabled());\n\n\t\t\tNacosPropertySourceRepository.collectNacosPropertySource(propertySource);\n\n\t\t\treturn new ConfigData(propertySources, getOptions(context, resource));\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tlog.error(\"Error getting properties from nacos: \" + resource, e);\n\t\t\tif (!resource.isOptional()) {\n\t\t\t\tthrow new ConfigDataResourceNotFoundException(resource, e);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate Option[] getOptions(ConfigDataLoaderContext context,\n\t\t\tNacosConfigDataResource resource) {\n\t\tList<Option> options = new ArrayList<>();\n\t\toptions.add(Option.IGNORE_IMPORTS);\n\t\toptions.add(Option.IGNORE_PROFILES);\n\t\tif (getPreference(context, resource) == REMOTE) {\n\t\t\t// mark it as 'PROFILE_SPECIFIC' config, it has higher priority,\n\t\t\t// will override the none profile specific config.\n\t\t\t// fixed https://github.com/alibaba/spring-cloud-alibaba/issues/2455\n\t\t\toptions.add(Option.PROFILE_SPECIFIC);\n\t\t}\n\t\treturn options.toArray(new Option[0]);\n\t}\n\n\tprivate ConfigPreference getPreference(ConfigDataLoaderContext context,\n\t\t\tNacosConfigDataResource resource) {\n\t\tBinder binder = context.getBootstrapContext().get(Binder.class);\n\t\tString prefix = NacosPropertiesPrefixer.getPrefix(binder);\n\n\n\t\tConfigPreference preference = binder\n\t\t\t\t.bind(prefix + \".config.preference\", ConfigPreference.class)\n\t\t\t\t.orElse(LOCAL);\n\t\tString specificPreference = resource.getConfig().getPreference();\n\t\tif (specificPreference != null) {\n\t\t\ttry {\n\t\t\t\tpreference = ConfigPreference.valueOf(specificPreference.toUpperCase(Locale.ROOT));\n\t\t\t}\n\t\t\tcatch (IllegalArgumentException ignore) {\n\t\t\t\t// illegal preference value, just ignore.\n\t\t\t\tlog.error(String.format(\n\t\t\t\t\t\t\"illegal preference value: %s, using default preference: %s\",\n\t\t\t\t\t\tspecificPreference, preference));\n\t\t\t}\n\t\t}\n\t\treturn preference;\n\t}\n\n\tprivate List<PropertySource<?>> pullConfig(ConfigService configService, String group,\n\t\t\tString dataId, String suffix, long timeout)\n\t\t\tthrows NacosException, IOException {\n\t\tString config = configService.getConfig(dataId, group, timeout);\n\t\tlogLoadInfo(group, dataId, config);\n\t\t// fixed issue: https://github.com/alibaba/spring-cloud-alibaba/issues/2906 .\n\t\tString configName = group + \"@\" + dataId;\n\t\treturn NacosDataParserHandler.getInstance().parseNacosData(configName, config, suffix);\n\t}\n\n\tprivate void logLoadInfo(String group, String dataId, String config) {\n\t\tif (config != null) {\n\t\t\tlog.info(String.format(\n\t\t\t\t\t\"[Nacos Config] Load config[dataId=%s, group=%s] success\", dataId,\n\t\t\t\t\tgroup));\n\t\t}\n\t\telse {\n\t\t\tlog.warn(String.format(\"[Nacos Config] config[dataId=%s, group=%s] is empty\",\n\t\t\t\t\tdataId, group));\n\t\t}\n\t\tif (log.isDebugEnabled()) {\n\t\t\tlog.debug(String.format(\n\t\t\t\t\t\"[Nacos Config] config[dataId=%s, group=%s] content: \\n%s\", dataId,\n\t\t\t\t\tgroup, config));\n\t\t}\n\t}\n\n\tprotected <T> T getBean(ConfigDataLoaderContext context, Class<T> type) {\n\t\tif (context.getBootstrapContext().isRegistered(type)) {\n\t\t\treturn context.getBootstrapContext().get(type);\n\t\t}\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataLocationResolver.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.configdata;\n\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.alibaba.cloud.nacos.NacosConfigManager;\nimport com.alibaba.cloud.nacos.NacosConfigProperties;\nimport com.alibaba.cloud.nacos.NacosPropertiesPrefixer;\nimport com.alibaba.cloud.nacos.utils.StringUtils;\nimport org.apache.commons.logging.Log;\n\nimport org.springframework.boot.bootstrap.BootstrapRegistry;\nimport org.springframework.boot.bootstrap.ConfigurableBootstrapContext;\nimport org.springframework.boot.context.config.ConfigDataLocation;\nimport org.springframework.boot.context.config.ConfigDataLocationNotFoundException;\nimport org.springframework.boot.context.config.ConfigDataLocationResolver;\nimport org.springframework.boot.context.config.ConfigDataLocationResolverContext;\nimport org.springframework.boot.context.config.ConfigDataResource;\nimport org.springframework.boot.context.config.ConfigDataResourceNotFoundException;\nimport org.springframework.boot.context.config.Profiles;\nimport org.springframework.boot.context.properties.bind.BindHandler;\nimport org.springframework.boot.context.properties.bind.Bindable;\nimport org.springframework.boot.context.properties.bind.Binder;\nimport org.springframework.boot.logging.DeferredLogFactory;\nimport org.springframework.core.Ordered;\n\nimport static com.alibaba.cloud.nacos.configdata.NacosConfigDataResource.NacosItemConfig;\nimport static com.alibaba.cloud.nacos.constants.Constants.SPRING_CONFIG_IMPORT_PROPERTIES;\n\n/**\n * Implementation of {@link ConfigDataLocationResolver}, load Nacos\n * {@link ConfigDataResource}.\n *\n * @author freeman\n * @since 2021.0.1.0\n */\npublic class NacosConfigDataLocationResolver\n\t\timplements ConfigDataLocationResolver<NacosConfigDataResource>, Ordered {\n\t/**\n\t * Prefix for Config Server imports.\n\t */\n\tpublic static final String PREFIX = \"nacos:\";\n\tprivate static final String GROUP = \"group\";\n\n\t// support params\n\tprivate static final String REFRESH_ENABLED = \"refreshEnabled\";\n\tprivate static final String PREFERENCE = \"preference\";\n\tprivate final Log log;\n\n\tpublic NacosConfigDataLocationResolver(DeferredLogFactory logFactory) {\n\t\tthis.log = logFactory.getLog(getClass());\n\t}\n\n\t@Override\n\tpublic int getOrder() {\n\t\treturn -1;\n\t}\n\n\tprotected NacosConfigProperties loadProperties(\n\t\t\tConfigDataLocationResolverContext context) {\n\t\tBinder binder = context.getBinder();\n\t\tBindHandler bindHandler = getBindHandler(context);\n\n\t\tNacosConfigProperties nacosConfigProperties;\n\t\tif (context.getBootstrapContext().isRegistered(NacosConfigDataLoadProperties.class)) {\n\t\t\tnacosConfigProperties = context.getBootstrapContext()\n\t\t\t\t\t.get(NacosConfigDataLoadProperties.class);\n\t\t}\n\t\telse {\n\t\t\tString nacosPrefix = NacosPropertiesPrefixer.getPrefix(context.getBinder());\n\n\t\t\tString nacosConfigPrefix = nacosPrefix + \".config\";\n\n\t\t\tnacosConfigProperties = binder\n\t\t\t\t\t.bind(nacosPrefix, Bindable.of(NacosConfigDataLoadProperties.class),\n\t\t\t\t\t\t\tbindHandler)\n\t\t\t\t\t.map(properties -> binder\n\t\t\t\t\t\t\t.bind(nacosConfigPrefix,\n\t\t\t\t\t\t\t\t\tBindable.ofInstance(properties), bindHandler)\n\t\t\t\t\t\t\t.orElse(properties))\n\t\t\t\t\t.orElseGet(() -> binder\n\t\t\t\t\t\t\t.bind(nacosConfigPrefix,\n\t\t\t\t\t\t\t\t\tBindable.of(NacosConfigDataLoadProperties.class), bindHandler)\n\t\t\t\t\t\t\t.orElseGet(NacosConfigDataLoadProperties::new));\n\t\t}\n\n\t\treturn nacosConfigProperties;\n\t}\n\n\tprivate BindHandler getBindHandler(ConfigDataLocationResolverContext context) {\n\t\treturn context.getBootstrapContext().getOrElse(BindHandler.class, null);\n\t}\n\n\tprotected Log getLog() {\n\t\treturn this.log;\n\t}\n\n\t@Override\n\tpublic boolean isResolvable(ConfigDataLocationResolverContext context,\n\t\t\tConfigDataLocation location) {\n\t\tif (!location.hasPrefix(getPrefix())) {\n\t\t\treturn false;\n\t\t}\n\t\tString prefix = NacosPropertiesPrefixer.getPrefix(context.getBinder());\n\n\t\treturn context.getBinder()\n\t\t\t\t.bind(prefix + \".config.enabled\", Boolean.class)\n\t\t\t\t.orElse(true);\n\t}\n\n\tprotected String getPrefix() {\n\t\treturn PREFIX;\n\t}\n\n\t@Override\n\tpublic List<NacosConfigDataResource> resolve(\n\t\t\tConfigDataLocationResolverContext context, ConfigDataLocation location)\n\t\t\tthrows ConfigDataLocationNotFoundException,\n\t\t\tConfigDataResourceNotFoundException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic List<NacosConfigDataResource> resolveProfileSpecific(\n\t\t\tConfigDataLocationResolverContext resolverContext,\n\t\t\tConfigDataLocation location, Profiles profiles)\n\t\t\tthrows ConfigDataLocationNotFoundException {\n\t\tNacosConfigProperties properties = loadProperties(resolverContext);\n\n\t\tConfigurableBootstrapContext bootstrapContext = resolverContext\n\t\t\t\t.getBootstrapContext();\n\n\t\tbootstrapContext.registerIfAbsent(NacosConfigProperties.class,\n\t\t\t\tBootstrapRegistry.InstanceSupplier.of(properties));\n\n\t\tregisterConfigManager(properties, bootstrapContext, resolverContext);\n\n\t\treturn loadConfigDataResources(location, profiles, properties);\n\t}\n\n\tprivate List<NacosConfigDataResource> loadConfigDataResources(\n\t\t\tConfigDataLocation location, Profiles profiles,\n\t\t\tNacosConfigProperties properties) {\n\t\tList<NacosConfigDataResource> result = new ArrayList<>();\n\t\tURI uri = getUri(location, properties);\n\n\t\tif (StringUtils.isBlank(dataIdFor(uri))) {\n\t\t\tthrow new IllegalArgumentException(\"dataId must be specified\");\n\t\t}\n\n\t\tNacosConfigDataResource resource = new NacosConfigDataResource(properties,\n\t\t\t\tlocation.isOptional(), profiles, log,\n\t\t\t\tnew NacosItemConfig().setGroup(groupFor(uri, properties))\n\t\t\t\t\t\t.setDataId(dataIdFor(uri)).setSuffix(suffixFor(uri, properties))\n\t\t\t\t\t\t.setRefreshEnabled(refreshEnabledFor(uri, properties))\n\t\t\t\t\t\t.setPreference(preferenceFor(uri)));\n\t\tresult.add(resource);\n\n\t\treturn result;\n\t}\n\n\tprivate String preferenceFor(URI uri) {\n\t\treturn getQueryMap(uri).get(PREFERENCE);\n\t}\n\n\tprivate URI getUri(ConfigDataLocation location, NacosConfigProperties properties) {\n\t\tString path = location.getNonPrefixedValue(getPrefix());\n\t\tif (StringUtils.isBlank(path)) {\n\t\t\tpath = \"/\";\n\t\t}\n\t\tif (!path.startsWith(\"/\")) {\n\t\t\tpath = \"/\" + path;\n\t\t}\n\t\tString uri = properties.getServerAddr() + path;\n\t\treturn getUri(uri);\n\t}\n\n\tprivate void registerConfigManager(NacosConfigProperties properties,\n\t\t\tConfigurableBootstrapContext bootstrapContext,\n\t\t\tConfigDataLocationResolverContext resolverContext) {\n\t\tList<?> springConfigImportProperties = resolverContext.getBinder()\n\t\t\t\t.bind(SPRING_CONFIG_IMPORT_PROPERTIES, List.class).get();\n\t\tif (!springConfigImportProperties.isEmpty() && !bootstrapContext.isRegistered(NacosConfigManager.class)) {\n\t\t\tbootstrapContext.register(NacosConfigManager.class,\n\t\t\t\t\tBootstrapRegistry.InstanceSupplier.of(NacosConfigManager.getInstance(properties)));\n\t\t}\n\t}\n\n\tprivate URI getUri(String uris) {\n\t\tif (!uris.startsWith(\"http://\") && !uris.startsWith(\"https://\")) {\n\t\t\turis = \"http://\" + uris;\n\t\t}\n\t\tURI uri;\n\t\ttry {\n\t\t\turi = new URI(uris);\n\t\t}\n\t\tcatch (URISyntaxException e) {\n\t\t\tthrow new IllegalArgumentException(\"illegal URI: \" + uris);\n\t\t}\n\t\treturn uri;\n\t}\n\n\tprivate String groupFor(URI uri, NacosConfigProperties properties) {\n\t\tMap<String, String> queryMap = getQueryMap(uri);\n\t\treturn queryMap.containsKey(GROUP) ? queryMap.get(GROUP) : properties.getGroup();\n\t}\n\n\tprivate Map<String, String> getQueryMap(URI uri) {\n\t\tString query = uri.getQuery();\n\t\tif (StringUtils.isBlank(query)) {\n\t\t\treturn Collections.emptyMap();\n\t\t}\n\t\tMap<String, String> result = new HashMap<>(4);\n\t\tfor (String entry : query.split(\"&\")) {\n\t\t\tString[] kv = entry.split(\"=\");\n\t\t\tif (kv.length == 2) {\n\t\t\t\tresult.put(kv[0], kv[1]);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate String suffixFor(URI uri, NacosConfigProperties properties) {\n\t\tString dataId = dataIdFor(uri);\n\t\tif (dataId != null && dataId.contains(\".\")) {\n\t\t\treturn dataId.substring(dataId.lastIndexOf('.') + 1);\n\t\t}\n\t\treturn properties.getFileExtension();\n\t}\n\n\tprivate boolean refreshEnabledFor(URI uri, NacosConfigProperties properties) {\n\t\tMap<String, String> queryMap = getQueryMap(uri);\n\t\treturn queryMap.containsKey(REFRESH_ENABLED)\n\t\t\t\t? Boolean.parseBoolean(queryMap.get(REFRESH_ENABLED))\n\t\t\t\t: properties.isRefreshEnabled();\n\t}\n\n\tprivate String dataIdFor(URI uri) {\n\t\tString path = uri.getPath();\n\t\t// notice '/'\n\t\tif (path == null || path.length() <= 1) {\n\t\t\treturn StringUtils.EMPTY;\n\t\t}\n\t\tString[] parts = path.substring(1).split(\"/\");\n\t\tif (parts.length != 1) {\n\t\t\tthrow new IllegalArgumentException(\"illegal dataId\");\n\t\t}\n\t\treturn parts[0];\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataResource.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.configdata;\n\nimport java.util.List;\nimport java.util.Objects;\n\nimport com.alibaba.cloud.nacos.NacosConfigProperties;\nimport org.apache.commons.logging.Log;\n\nimport org.springframework.boot.context.config.ConfigDataResource;\nimport org.springframework.boot.context.config.Profiles;\nimport org.springframework.util.StringUtils;\n\n/**\n * @author freeman\n * @since 2021.0.1.0\n */\npublic class NacosConfigDataResource extends ConfigDataResource {\n\n\tprivate final NacosConfigProperties properties;\n\n\tprivate final boolean optional;\n\n\tprivate final Profiles profiles;\n\n\tprivate final Log log;\n\n\tprivate final NacosItemConfig config;\n\n\tpublic NacosConfigDataResource(NacosConfigProperties properties, boolean optional,\n\t\t\tProfiles profiles, Log log, NacosItemConfig config) {\n\t\tthis.properties = properties;\n\t\tthis.optional = optional;\n\t\tthis.profiles = profiles;\n\t\tthis.log = log;\n\t\tthis.config = config;\n\t}\n\n\tpublic NacosConfigProperties getProperties() {\n\t\treturn this.properties;\n\t}\n\n\tpublic boolean isOptional() {\n\t\treturn this.optional;\n\t}\n\n\tpublic String getProfiles() {\n\t\treturn StringUtils.collectionToCommaDelimitedString(getAcceptedProfiles());\n\t}\n\n\tList<String> getAcceptedProfiles() {\n\t\treturn this.profiles.getAccepted();\n\t}\n\n\tpublic Log getLog() {\n\t\treturn this.log;\n\t}\n\n\tpublic NacosItemConfig getConfig() {\n\t\treturn config;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (this == o) {\n\t\t\treturn true;\n\t\t}\n\t\tif (o == null || getClass() != o.getClass()) {\n\t\t\treturn false;\n\t\t}\n\t\tNacosConfigDataResource that = (NacosConfigDataResource) o;\n\t\treturn optional == that.optional && Objects.equals(properties, that.properties)\n\t\t\t\t&& Objects.equals(profiles, that.profiles)\n\t\t\t\t&& Objects.equals(log, that.log) && Objects.equals(config, that.config);\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn Objects.hash(properties, optional, profiles, log, config);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"NacosConfigDataResource{\" + \"properties=\" + properties + \", optional=\"\n\t\t\t\t+ optional + \", profiles=\" + profiles + \", config=\" + config + '}';\n\t}\n\n\tpublic static class NacosItemConfig {\n\t\tprivate String group;\n\t\tprivate String dataId;\n\t\tprivate String suffix;\n\t\tprivate boolean refreshEnabled;\n\t\tprivate String preference;\n\n\t\tpublic NacosItemConfig() {\n\t\t}\n\n\t\tpublic NacosItemConfig(String group, String dataId, String suffix,\n\t\t\t\tboolean refreshEnabled, String preference) {\n\t\t\tthis.group = group;\n\t\t\tthis.dataId = dataId;\n\t\t\tthis.suffix = suffix;\n\t\t\tthis.refreshEnabled = refreshEnabled;\n\t\t\tthis.preference = preference;\n\t\t}\n\n\t\tpublic NacosItemConfig setGroup(String group) {\n\t\t\tthis.group = group;\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic NacosItemConfig setDataId(String dataId) {\n\t\t\tthis.dataId = dataId;\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic NacosItemConfig setSuffix(String suffix) {\n\t\t\tthis.suffix = suffix;\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic NacosItemConfig setRefreshEnabled(boolean refreshEnabled) {\n\t\t\tthis.refreshEnabled = refreshEnabled;\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic NacosItemConfig setPreference(String preference) {\n\t\t\tthis.preference = preference;\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic String getGroup() {\n\t\t\treturn group;\n\t\t}\n\n\t\tpublic String getDataId() {\n\t\t\treturn dataId;\n\t\t}\n\n\t\tpublic String getSuffix() {\n\t\t\treturn suffix;\n\t\t}\n\n\t\tpublic boolean isRefreshEnabled() {\n\t\t\treturn refreshEnabled;\n\t\t}\n\n\t\tpublic String getPreference() {\n\t\t\treturn preference;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean equals(Object o) {\n\t\t\tif (this == o) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (o == null || getClass() != o.getClass()) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tNacosItemConfig that = (NacosItemConfig) o;\n\t\t\treturn refreshEnabled == that.refreshEnabled\n\t\t\t\t\t&& Objects.equals(group, that.group)\n\t\t\t\t\t&& Objects.equals(dataId, that.dataId)\n\t\t\t\t\t&& Objects.equals(suffix, that.suffix)\n\t\t\t\t\t&& Objects.equals(preference, that.preference);\n\t\t}\n\n\t\t@Override\n\t\tpublic int hashCode() {\n\t\t\treturn Objects.hash(group, dataId, suffix, refreshEnabled, preference);\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn \"NacosItemConfig{\" + \"group='\" + group + '\\'' + \", dataId='\" + dataId\n\t\t\t\t\t+ '\\'' + \", suffix='\" + suffix + '\\'' + \", refreshEnabled=\"\n\t\t\t\t\t+ refreshEnabled + \", preference=\" + preference + '}';\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/constants/Constants.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.constants;\n\n\n/**\n * @author <a href=\"mailto:chiangzeon@gmail.com\">chiangzeon</a>\n */\npublic final class Constants {\n\n\tprivate Constants() {\n\t}\n\n\t/**\n\t * property:spring.config.import.\n\t */\n\tpublic static final String SPRING_CONFIG_IMPORT_PROPERTIES = \"spring.config.import\";\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/diagnostics/analyzer/NacosConnectionFailureAnalyzer.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.diagnostics.analyzer;\n\nimport org.springframework.boot.diagnostics.AbstractFailureAnalyzer;\nimport org.springframework.boot.diagnostics.FailureAnalysis;\n\n/**\n * A {@code FailureAnalyzer} that performs analysis of failures caused by a\n * {@code NacosConnectionFailureException}.\n *\n * @author juven.xuxb\n */\npublic class NacosConnectionFailureAnalyzer\n\t\textends AbstractFailureAnalyzer<com.alibaba.cloud.nacos.diagnostics.analyzer.NacosConnectionFailureException> {\n\n\t@Override\n\tprotected FailureAnalysis analyze(Throwable rootFailure,\n\t\t\tcom.alibaba.cloud.nacos.diagnostics.analyzer.NacosConnectionFailureException cause) {\n\t\treturn new FailureAnalysis(\n\t\t\t\t\"Application failed to connect to Nacos server: \\\"\"\n\t\t\t\t\t\t+ cause.getServerAddr() + \"\\\"\",\n\t\t\t\t\"Please check your Nacos server config\", cause);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/diagnostics/analyzer/NacosConnectionFailureException.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.diagnostics.analyzer;\n\n/**\n * A {@code NacosConnectionFailureException} is thrown when the application fails to\n * connect to Nacos Server.\n *\n * @author juven.xuxb\n */\npublic class NacosConnectionFailureException extends RuntimeException {\n\n\tprivate final String serverAddr;\n\n\tpublic NacosConnectionFailureException(String serverAddr, String message) {\n\t\tsuper(message);\n\t\tthis.serverAddr = serverAddr;\n\t}\n\n\tpublic NacosConnectionFailureException(String serverAddr, String message,\n\t\t\tThrowable cause) {\n\t\tsuper(message, cause);\n\t\tthis.serverAddr = serverAddr;\n\t}\n\n\tpublic String getServerAddr() {\n\t\treturn serverAddr;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosConfigEndpoint.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.endpoint;\n\nimport java.text.DateFormat;\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.alibaba.cloud.nacos.NacosConfigProperties;\nimport com.alibaba.cloud.nacos.NacosPropertySourceRepository;\nimport com.alibaba.cloud.nacos.client.NacosPropertySource;\nimport com.alibaba.cloud.nacos.refresh.NacosRefreshHistory;\n\nimport org.springframework.boot.actuate.endpoint.annotation.Endpoint;\nimport org.springframework.boot.actuate.endpoint.annotation.ReadOperation;\n\n/**\n * Endpoint for Nacos, contains config data and refresh history.\n *\n * @author xiaojing\n */\n@Endpoint(id = \"nacosconfig\")\npublic class NacosConfigEndpoint {\n\n\tprivate final NacosConfigProperties properties;\n\n\tprivate final NacosRefreshHistory refreshHistory;\n\n\tprivate ThreadLocal<DateFormat> dateFormat = ThreadLocal\n\t\t\t.withInitial(() -> new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\"));\n\n\tpublic NacosConfigEndpoint(NacosConfigProperties properties,\n\t\t\tNacosRefreshHistory refreshHistory) {\n\t\tthis.properties = properties;\n\t\tthis.refreshHistory = refreshHistory;\n\t}\n\n\t@ReadOperation\n\tpublic Map<String, Object> invoke() {\n\t\tMap<String, Object> result = new HashMap<>(16);\n\t\tresult.put(\"NacosConfigProperties\", properties);\n\n\t\tList<NacosPropertySource> all = NacosPropertySourceRepository.getAll();\n\n\t\tList<Map<String, Object>> sources = new ArrayList<>();\n\t\tfor (NacosPropertySource ps : all) {\n\t\t\tMap<String, Object> source = new HashMap<>(16);\n\t\t\tsource.put(\"dataId\", ps.getDataId());\n\t\t\tsource.put(\"lastSynced\", dateFormat.get().format(ps.getTimestamp()));\n\t\t\tsources.add(source);\n\t\t}\n\t\tresult.put(\"Sources\", sources);\n\t\tresult.put(\"RefreshHistory\", refreshHistory.getRecords());\n\n\t\treturn result;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosConfigEndpointAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.endpoint;\n\nimport com.alibaba.cloud.nacos.NacosConfigEnabledCondition;\nimport com.alibaba.cloud.nacos.NacosConfigManager;\nimport com.alibaba.cloud.nacos.refresh.NacosRefreshHistory;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;\nimport org.springframework.boot.actuate.endpoint.annotation.Endpoint;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;\nimport org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Conditional;\n\n/**\n * @author xiaojing\n */\n@ConditionalOnWebApplication\n@ConditionalOnClass(Endpoint.class)\n@Conditional(NacosConfigEnabledCondition.class)\npublic class NacosConfigEndpointAutoConfiguration {\n\n\t@Autowired\n\tprivate NacosConfigManager nacosConfigManager;\n\n\t@Autowired\n\tprivate NacosRefreshHistory nacosRefreshHistory;\n\n\t@ConditionalOnMissingBean\n\t@ConditionalOnAvailableEndpoint\n\t@Bean\n\tpublic NacosConfigEndpoint nacosConfigEndpoint() {\n\t\treturn new NacosConfigEndpoint(nacosConfigManager.getNacosConfigProperties(),\n\t\t\t\tnacosRefreshHistory);\n\t}\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\t@ConditionalOnProperty(name = \"spring.nacos.config.health-indicator.enabled\", havingValue = \"true\", matchIfMissing = false)\n\t@ConditionalOnEnabledHealthIndicator(\"nacos-config\")\n\tpublic NacosConfigHealthIndicator nacosConfigHealthIndicator() {\n\t\treturn new NacosConfigHealthIndicator(nacosConfigManager.getConfigService());\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosConfigHealthIndicator.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.endpoint;\n\nimport com.alibaba.nacos.api.config.ConfigService;\n\nimport org.springframework.boot.health.contributor.AbstractHealthIndicator;\nimport org.springframework.boot.health.contributor.Health;\nimport org.springframework.boot.health.contributor.HealthIndicator;\n\n/**\n * The {@link HealthIndicator} for Nacos Config.\n *\n * @author xiaojing\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n */\npublic class NacosConfigHealthIndicator extends AbstractHealthIndicator {\n\n\tprivate final ConfigService configService;\n\n\t/**\n\t * status up .\n\t */\n\tprivate final String STATUS_UP = \"UP\";\n\n\t/**\n\t * status down .\n\t */\n\tprivate final String STATUS_DOWN = \"DOWN\";\n\n\tpublic NacosConfigHealthIndicator(ConfigService configService) {\n\t\tthis.configService = configService;\n\t}\n\n\t@Override\n\tprotected void doHealthCheck(Health.Builder builder) throws Exception {\n\t\t// Just return \"UP\" or \"DOWN\"\n\t\tString status = configService.getServerStatus();\n\t\t// Set the status to Builder\n\t\tbuilder.status(status);\n\t\tswitch (status) {\n\t\tcase STATUS_UP -> builder.up();\n\t\tcase STATUS_DOWN -> builder.down();\n\t\tdefault -> builder.unknown();\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/AbstractPropertySourceLoader.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.parser;\n\nimport java.io.IOException;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Set;\n\nimport com.alibaba.cloud.nacos.utils.StringUtils;\n\nimport org.springframework.boot.env.PropertySourceLoader;\nimport org.springframework.core.env.PropertySource;\nimport org.springframework.core.io.Resource;\n\n/**\n * Nacos-specific loader, If need to support other methods of parsing,you need to do the\n * following steps:\n * <p>\n * 1.inherit {@link AbstractPropertySourceLoader};<br>\n * 2. define the file{@code spring.factories} and append\n * {@code org.springframework.boot.env.PropertySourceLoader=..};<br>\n * 3.the last step validate.\n * </p>\n * Notice the use of {@link NacosByteArrayResource} .\n *\n * @author zkz\n */\npublic abstract class AbstractPropertySourceLoader implements PropertySourceLoader {\n\n\t/**\n\t * symbol: dot.\n\t */\n\tstatic final String DOT = \".\";\n\n\t/**\n\t * Prevent interference with other loaders.Nacos-specific loader, unless the reload\n\t * changes it.\n\t * @param name the root name of the property source. If multiple documents are loaded\n\t * an additional suffix should be added to the name for each source loaded.\n\t * @param resource the resource to load\n\t * @return if the resource can be loaded\n\t */\n\tprotected boolean canLoad(String name, Resource resource) {\n\t\treturn resource instanceof NacosByteArrayResource;\n\t}\n\n\t/**\n\t * Load the resource into one or more property sources. Implementations may either\n\t * return a list containing a single source, or in the case of a multi-document format\n\t * such as yaml a source for each document in the resource.\n\t * @param name the root name of the property source. If multiple documents are loaded\n\t * an additional suffix should be added to the name for each source loaded.\n\t * @param resource the resource to load\n\t * @return a list property sources\n\t * @throws IOException if the source cannot be loaded\n\t */\n\t@Override\n\tpublic List<PropertySource<?>> load(String name, Resource resource)\n\t\t\tthrows IOException {\n\t\tif (!canLoad(name, resource)) {\n\t\t\treturn Collections.emptyList();\n\t\t}\n\t\treturn this.doLoad(name, resource);\n\t}\n\n\t/**\n\t * Load the resource into one or more property sources. Implementations may either\n\t * return a list containing a single source, or in the case of a multi-document format\n\t * such as yaml a source for each document in the resource.\n\t * @param name the root name of the property source. If multiple documents are loaded\n\t * an additional suffix should be added to the name for each source loaded.\n\t * @param resource the resource to load\n\t * @return a list property sources\n\t * @throws IOException if the source cannot be loaded\n\t */\n\tprotected abstract List<PropertySource<?>> doLoad(String name, Resource resource)\n\t\t\tthrows IOException;\n\n\tprotected void flattenedMap(Map<String, Object> result, Map<String, Object> dataMap,\n\t\t\tString parentKey) {\n\t\tif (dataMap == null || dataMap.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\tSet<Entry<String, Object>> entries = dataMap.entrySet();\n\t\tfor (Iterator<Entry<String, Object>> iterator = entries.iterator(); iterator\n\t\t\t\t.hasNext();) {\n\t\t\tMap.Entry<String, Object> entry = iterator.next();\n\t\t\tString key = entry.getKey();\n\t\t\tObject value = entry.getValue();\n\n\t\t\tString fullKey = StringUtils.isEmpty(parentKey) ? key : key.startsWith(\"[\")\n\t\t\t\t\t? parentKey.concat(key) : parentKey.concat(DOT).concat(key);\n\n\t\t\tif (value instanceof Map map) {\n\t\t\t\tflattenedMap(result, map, fullKey);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\telse if (value instanceof Collection collection) {\n\t\t\t\tint count = 0;\n\t\t\t\tfor (Object object : collection) {\n\t\t\t\t\tflattenedMap(result,\n\t\t\t\t\t\t\tCollections.singletonMap(\"[\" + (count++) + \"]\", object),\n\t\t\t\t\t\t\tfullKey);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tresult.put(fullKey, value);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosByteArrayResource.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.parser;\n\nimport org.springframework.core.io.ByteArrayResource;\n\n/**\n * Nacos-specific resource.\n *\n * @author zkz\n */\npublic class NacosByteArrayResource extends ByteArrayResource {\n\n\tprivate String filename;\n\n\t/**\n\t * Create a new {@code ByteArrayResource}.\n\t * @param byteArray the byte array to wrap\n\t */\n\tpublic NacosByteArrayResource(byte[] byteArray) {\n\t\tsuper(byteArray);\n\t}\n\n\t/**\n\t * Create a new {@code ByteArrayResource} with a description.\n\t * @param byteArray the byte array to wrap\n\t * @param description where the byte array comes from\n\t */\n\tpublic NacosByteArrayResource(byte[] byteArray, String description) {\n\t\tsuper(byteArray, description);\n\t}\n\n\tpublic void setFilename(String filename) {\n\t\tthis.filename = filename;\n\t}\n\n\t/**\n\t * This implementation always returns {@code null}, assuming that this resource type\n\t * does not have a filename.\n\t */\n\t@Override\n\tpublic String getFilename() {\n\t\treturn null == this.filename ? this.getDescription() : this.filename;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataParserHandler.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.parser;\n\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\n\nimport com.alibaba.cloud.nacos.utils.NacosConfigUtils;\n\nimport org.springframework.boot.env.OriginTrackedMapPropertySource;\nimport org.springframework.boot.env.PropertiesPropertySourceLoader;\nimport org.springframework.boot.env.PropertySourceLoader;\nimport org.springframework.core.env.EnumerablePropertySource;\nimport org.springframework.core.env.PropertySource;\nimport org.springframework.core.io.support.SpringFactoriesLoader;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.util.StringUtils;\n\nimport static com.alibaba.cloud.nacos.parser.AbstractPropertySourceLoader.DOT;\n\n/**\n * @author zkz\n */\npublic final class NacosDataParserHandler {\n\n\t/**\n\t * default extension.\n\t */\n\tprivate static final String DEFAULT_EXTENSION = \"properties\";\n\n\tprivate static List<PropertySourceLoader> propertySourceLoaders;\n\n\tprivate NacosDataParserHandler() {\n\t\tpropertySourceLoaders = SpringFactoriesLoader\n\t\t\t\t.loadFactories(PropertySourceLoader.class, getClass().getClassLoader());\n\t}\n\n\t/**\n\t * Parsing nacos configuration content.\n\t * @param configName name of nacos-config\n\t * @param configValue value from nacos-config\n\t * @param extension identifies the type of configValue\n\t * @return result of Map\n\t * @throws IOException thrown if there is a problem parsing config.\n\t */\n\tpublic List<PropertySource<?>> parseNacosData(String configName, String configValue,\n\t\t\tString extension) throws IOException {\n\t\tif (!StringUtils.hasLength(configValue)) {\n\t\t\treturn Collections.emptyList();\n\t\t}\n\t\tif (!StringUtils.hasLength(extension)) {\n\t\t\textension = this.getFileExtension(configName);\n\t\t}\n\t\tfor (PropertySourceLoader propertySourceLoader : propertySourceLoaders) {\n\t\t\tif (!canLoadFileExtension(propertySourceLoader, extension)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tNacosByteArrayResource nacosByteArrayResource;\n\t\t\tif (propertySourceLoader instanceof PropertiesPropertySourceLoader) {\n\t\t\t\t// PropertiesPropertySourceLoader internal is to use the ISO_8859_1,\n\t\t\t\t// the Chinese will be garbled, needs to transform into unicode.\n\t\t\t\tnacosByteArrayResource = new NacosByteArrayResource(\n\t\t\t\t\t\tNacosConfigUtils.selectiveConvertUnicode(configValue).getBytes(),\n\t\t\t\t\t\tconfigName);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tnacosByteArrayResource = new NacosByteArrayResource(\n\t\t\t\t\t\tconfigValue.getBytes(), configName);\n\t\t\t}\n\t\t\tnacosByteArrayResource.setFilename(getFileName(configName, extension));\n\t\t\tList<PropertySource<?>> propertySourceList = propertySourceLoader\n\t\t\t\t\t.load(configName, nacosByteArrayResource);\n\t\t\tif (CollectionUtils.isEmpty(propertySourceList)) {\n\t\t\t\treturn Collections.emptyList();\n\t\t\t}\n\t\t\treturn propertySourceList.stream().filter(Objects::nonNull)\n\t\t\t\t\t.map(propertySource -> {\n\t\t\t\t\t\tif (propertySource instanceof EnumerablePropertySource enumerablePropertySource) {\n\t\t\t\t\t\t\tString[] propertyNames = enumerablePropertySource\n\t\t\t\t\t\t\t\t\t.getPropertyNames();\n\t\t\t\t\t\t\tif (propertyNames != null && propertyNames.length > 0) {\n\t\t\t\t\t\t\t\tMap<String, Object> map = new LinkedHashMap<>();\n\t\t\t\t\t\t\t\tArrays.stream(propertyNames).forEach(name -> {\n\t\t\t\t\t\t\t\t\tmap.put(name, propertySource.getProperty(name));\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\treturn new OriginTrackedMapPropertySource(\n\t\t\t\t\t\t\t\t\t\tpropertySource.getName(), map, true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn propertySource;\n\t\t\t\t\t}).collect(Collectors.toList());\n\t\t}\n\t\treturn Collections.emptyList();\n\t}\n\n\t/**\n\t * check the current extension can be processed.\n\t * @param loader the propertySourceLoader\n\t * @param extension file extension\n\t * @return if can match extension\n\t */\n\tprivate boolean canLoadFileExtension(PropertySourceLoader loader, String extension) {\n\t\treturn Arrays.stream(loader.getFileExtensions())\n\t\t\t\t.anyMatch((fileExtension) -> StringUtils.endsWithIgnoreCase(extension,\n\t\t\t\t\t\tfileExtension));\n\t}\n\n\t/**\n\t * @param name filename\n\t * @return file extension, default {@code DEFAULT_EXTENSION} if don't get\n\t */\n\tpublic String getFileExtension(String name) {\n\t\tif (!StringUtils.hasLength(name)) {\n\t\t\treturn DEFAULT_EXTENSION;\n\t\t}\n\t\tint idx = name.lastIndexOf(DOT);\n\t\tif (idx > 0 && idx < name.length() - 1) {\n\t\t\treturn name.substring(idx + 1);\n\t\t}\n\t\treturn DEFAULT_EXTENSION;\n\t}\n\n\tprivate String getFileName(String name, String extension) {\n\t\tif (!StringUtils.hasLength(extension)) {\n\t\t\treturn name;\n\t\t}\n\t\tif (!StringUtils.hasLength(name)) {\n\t\t\treturn extension;\n\t\t}\n\t\tint idx = name.lastIndexOf(DOT);\n\t\tif (idx > 0 && idx < name.length() - 1) {\n\t\t\tString ext = name.substring(idx + 1);\n\t\t\tif (extension.equalsIgnoreCase(ext)) {\n\t\t\t\treturn name;\n\t\t\t}\n\t\t}\n\t\treturn name + DOT + extension;\n\t}\n\n\tpublic static NacosDataParserHandler getInstance() {\n\t\treturn ParserHandler.HANDLER;\n\t}\n\n\tprivate static final class ParserHandler {\n\n\t\tprivate static final NacosDataParserHandler HANDLER = new NacosDataParserHandler();\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosJsonPropertySourceLoader.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.parser;\n\nimport java.io.IOException;\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.fasterxml.jackson.core.JsonParser;\nimport com.fasterxml.jackson.databind.ObjectMapper;\n\nimport org.springframework.boot.env.OriginTrackedMapPropertySource;\nimport org.springframework.core.env.PropertySource;\nimport org.springframework.core.io.Resource;\n\n/**\n * @author zkz\n */\npublic class NacosJsonPropertySourceLoader extends AbstractPropertySourceLoader {\n\n\t/**\n\t * constant.\n\t */\n\tprivate static final String VALUE = \"value\";\n\n\t/**\n\t * Returns the file extensions that the loader supports (excluding the '.').\n\t * @return the file extensions\n\t */\n\t@Override\n\tpublic String[] getFileExtensions() {\n\t\treturn new String[] { \"json\" };\n\t}\n\n\t/**\n\t * Load the resource into one or more property sources. Implementations may either\n\t * return a list containing a single source, or in the case of a multi-document format\n\t * such as yaml a source for each document in the resource.\n\t * @param name the root name of the property source. If multiple documents are loaded\n\t * an additional suffix should be added to the name for each source loaded.\n\t * @param resource the resource to load\n\t * @return a list property sources\n\t * @throws IOException if the source cannot be loaded\n\t */\n\t@Override\n\tprotected List<PropertySource<?>> doLoad(String name, Resource resource)\n\t\t\tthrows IOException {\n\t\tMap<String, Object> result = new LinkedHashMap<>(32);\n\t\tObjectMapper mapper = new ObjectMapper();\n\t\t// [fix issue #3043] support comment in json config\n\t\tmapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);\n\t\tMap<String, Object> nacosDataMap = mapper.readValue(resource.getInputStream(),\n\t\t\t\tLinkedHashMap.class);\n\t\tflattenedMap(result, nacosDataMap, null);\n\t\treturn Collections.singletonList(\n\t\t\t\tnew OriginTrackedMapPropertySource(name, this.reloadMap(result), true));\n\n\t}\n\n\t/**\n\t * Reload the key ending in `value` if need.\n\t */\n\tprotected Map<String, Object> reloadMap(Map<String, Object> map) {\n\t\tif (map == null || map.isEmpty()) {\n\t\t\treturn null;\n\t\t}\n\t\tMap<String, Object> result = new LinkedHashMap<>(map);\n\t\tfor (Map.Entry<String, Object> entry : map.entrySet()) {\n\t\t\tString key = entry.getKey();\n\t\t\tif (key.contains(AbstractPropertySourceLoader.DOT)) {\n\t\t\t\tint idx = key.lastIndexOf(AbstractPropertySourceLoader.DOT);\n\t\t\t\tString suffix = key.substring(idx + 1);\n\t\t\t\tif (VALUE.equalsIgnoreCase(suffix)) {\n\t\t\t\t\tresult.put(key.substring(0, idx), entry.getValue());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosXmlPropertySourceLoader.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.parser;\n\nimport java.io.IOException;\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport javax.xml.parsers.DocumentBuilder;\nimport javax.xml.parsers.DocumentBuilderFactory;\n\nimport com.alibaba.cloud.nacos.utils.StringUtils;\nimport org.w3c.dom.Document;\nimport org.w3c.dom.NamedNodeMap;\nimport org.w3c.dom.Node;\nimport org.w3c.dom.NodeList;\n\nimport org.springframework.boot.env.OriginTrackedMapPropertySource;\nimport org.springframework.boot.env.PropertiesPropertySourceLoader;\nimport org.springframework.core.Ordered;\nimport org.springframework.core.env.PropertySource;\nimport org.springframework.core.io.Resource;\n\n/**\n * Parsing for XML requires overwriting the default\n * {@link PropertiesPropertySourceLoader}, because it internally rigorously validates\n * ({@code DOCTYPE}) THE XML in a way that makes it difficult to customize the\n * configuration; at finally, make sure it's in the first place.\n *\n * @author zkz\n */\npublic class NacosXmlPropertySourceLoader extends AbstractPropertySourceLoader\n\t\timplements Ordered {\n\n\t/**\n\t * Get the order value of this object.\n\t * <p>\n\t * Higher values are interpreted as lower priority. As a consequence, the object with\n\t * the lowest value has the highest priority (somewhat analogous to Servlet\n\t * {@code load-on-startup} values).\n\t * <p>\n\t * Same order values will result in arbitrary sort positions for the affected objects.\n\t * @return the order value\n\t * @see #HIGHEST_PRECEDENCE\n\t * @see #LOWEST_PRECEDENCE\n\t */\n\t@Override\n\tpublic int getOrder() {\n\t\treturn Integer.MIN_VALUE;\n\t}\n\n\t/**\n\t * Returns the file extensions that the loader supports (excluding the '.').\n\t * @return the file extensions\n\t */\n\t@Override\n\tpublic String[] getFileExtensions() {\n\t\treturn new String[] { \"xml\" };\n\t}\n\n\t/**\n\t * Load the resource into one or more property sources. Implementations may either\n\t * return a list containing a single source, or in the case of a multi-document format\n\t * such as yaml a source for each document in the resource.\n\t * @param name the root name of the property source. If multiple documents are loaded\n\t * an additional suffix should be added to the name for each source loaded.\n\t * @param resource the resource to load\n\t * @return a list property sources\n\t * @throws IOException if the source cannot be loaded\n\t */\n\t@Override\n\tprotected List<PropertySource<?>> doLoad(String name, Resource resource)\n\t\t\tthrows IOException {\n\t\tMap<String, Object> nacosDataMap = parseXml2Map(resource);\n\t\treturn Collections.singletonList(\n\t\t\t\tnew OriginTrackedMapPropertySource(name, nacosDataMap, true));\n\n\t}\n\n\tprivate Map<String, Object> parseXml2Map(Resource resource) throws IOException {\n\t\tMap<String, Object> map = new LinkedHashMap<>(32);\n\t\ttry {\n\t\t\tDocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance()\n\t\t\t\t\t.newDocumentBuilder();\n\t\t\tDocument document = documentBuilder.parse(resource.getInputStream());\n\t\t\tif (null == document) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tparseNodeList(document.getChildNodes(), map, \"\");\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new IOException(\"The xml content parse error.\", e.getCause());\n\t\t}\n\t\treturn map;\n\t}\n\n\tprivate void parseNodeList(NodeList nodeList, Map<String, Object> map,\n\t\t\tString parentKey) {\n\t\tif (nodeList == null || nodeList.getLength() < 1) {\n\t\t\treturn;\n\t\t}\n\t\tparentKey = parentKey == null ? \"\" : parentKey;\n\t\tfor (int i = 0; i < nodeList.getLength(); i++) {\n\t\t\tNode node = nodeList.item(i);\n\t\t\tString value = node.getNodeValue();\n\t\t\tvalue = value == null ? \"\" : value.trim();\n\t\t\tString name = node.getNodeName();\n\t\t\tname = name == null ? \"\" : name.trim();\n\n\t\t\tif (StringUtils.isEmpty(name)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tString key = StringUtils.isEmpty(parentKey) ? name : parentKey + AbstractPropertySourceLoader.DOT + name;\n\t\t\tNamedNodeMap nodeMap = node.getAttributes();\n\t\t\tparseNodeAttr(nodeMap, map, key);\n\t\t\tif (node.getNodeType() == Node.ELEMENT_NODE && node.hasChildNodes()) {\n\t\t\t\tparseNodeList(node.getChildNodes(), map, key);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (value.length() < 1) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tmap.put(parentKey, value);\n\t\t}\n\t}\n\n\tprivate void parseNodeAttr(NamedNodeMap nodeMap, Map<String, Object> map,\n\t\t\tString parentKey) {\n\t\tif (null == nodeMap || nodeMap.getLength() < 1) {\n\t\t\treturn;\n\t\t}\n\t\tfor (int i = 0; i < nodeMap.getLength(); i++) {\n\t\t\tNode node = nodeMap.item(i);\n\t\t\tif (null == node) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (node.getNodeType() == Node.ATTRIBUTE_NODE) {\n\t\t\t\tif (StringUtils.isEmpty(node.getNodeName())) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (StringUtils.isEmpty(node.getNodeValue())) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tmap.put(String.join(AbstractPropertySourceLoader.DOT, parentKey, node.getNodeName()),\n\t\t\t\t\t\tnode.getNodeValue());\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/proxy/druid/NacosDruidConfigFilter.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.proxy.druid;\n\nimport java.io.StringReader;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.Set;\n\nimport com.alibaba.cloud.nacos.NacosConfigManager;\nimport com.alibaba.cloud.nacos.utils.StringUtils;\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxy;\nimport com.alibaba.nacos.api.config.ConfigService;\nimport com.alibaba.nacos.api.config.listener.AbstractListener;\nimport com.alibaba.nacos.api.exception.NacosException;\n\npublic class NacosDruidConfigFilter extends FilterAdapter {\n\n\tprivate final static String groupMatched = \"nacos-datasource\";\n\n\tprivate final Set<String> idempotentControl = new HashSet<>();\n\n\tprivate final String proxyDataId;\n\n\tpublic NacosDruidConfigFilter(String proxyDataId) {\n\t\tthis.proxyDataId = proxyDataId;\n\t}\n\n\t@Override\n\tpublic void init(final DataSourceProxy dataSourceProxy) {\n\n\t\tif (!(dataSourceProxy instanceof DruidDataSource)) {\n\t\t\treturn;\n\t\t}\n\t\tString name = StringUtils.isNotBlank(dataSourceProxy.getName()) ? dataSourceProxy.getName()\n\t\t\t\t: String.valueOf(dataSourceProxy.hashCode());\n\t\tif (idempotentControl.contains(name)) {\n\t\t\treturn;\n\t\t}\n\n\t\tDruidDataSource druidDataSource = ((DruidDataSource) dataSourceProxy);\n\t\tConfigService configService = NacosConfigManager.getInstance().getConfigService();\n\n\t\ttry {\n\t\t\tString druidProperties = configService.getConfig(proxyDataId, groupMatched, 3000L);\n\t\t\tProperties propertiesNew = convert(druidProperties);\n\t\t\tdruidDataSource.configFromProperties(propertiesNew);\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\n\t\t//register listeners\n\t\ttry {\n\t\t\tconfigService.addListener(proxyDataId, groupMatched, new AbstractListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic void receiveConfigInfo(String configInfo) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tProperties propertiesNew = convert(configInfo);\n\n\t\t\t\t\t\t//refresh\n\t\t\t\t\t\t((DruidDataSource) dataSourceProxy).configFromProperties(propertiesNew);\n\t\t\t\t\t}\n\t\t\t\t\tcatch (Exception e) {\n\t\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tcatch (NacosException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\tidempotentControl.add(name);\n\t}\n\n\tprivate static final String druidPrefix = \"spring.datasource.druid.\";\n\n\tprivate static final String datasourcePrefix = \"spring.datasource.\";\n\n\tprivate static Properties convert(String config) throws Exception {\n\n\t\tProperties properties = new Properties();\n\t\tproperties.load(new StringReader(config));\n\n\t\tProperties propertiesNew = new Properties();\n\t\tIterator<Map.Entry<Object, Object>> iterator = properties.entrySet().iterator();\n\t\twhile (iterator.hasNext()) {\n\t\t\tMap.Entry<Object, Object> entry = iterator.next();\n\t\t\tString key = entry.getKey().toString();\n\t\t\tString value = entry.getValue().toString();\n\n\t\t\tif (key.startsWith(druidPrefix)) {\n\t\t\t\tpropertiesNew.put(key.replace(druidPrefix, \"druid.\"), value);\n\t\t\t}\n\t\t\telse if (key.startsWith(datasourcePrefix)) {\n\t\t\t\tpropertiesNew.put(key.replace(datasourcePrefix, \"druid.\"), value);\n\t\t\t}\n\t\t}\n\n\t\treturn propertiesNew;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/proxy/druid/NacosDruidFilterConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.proxy.druid;\n\nimport com.alibaba.cloud.nacos.NacosConfigManager;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.env.Environment;\n\n@Configuration\npublic class NacosDruidFilterConfiguration {\n\n\t@Bean\n\t@ConditionalOnProperty(value = \"spring.nacos.config.proxy.druid.enabled\", havingValue = \"true\")\n\t@ConditionalOnBean(NacosConfigManager.class)\n\tpublic NacosDruidConfigFilter nacosDruidFilter(Environment environment) {\n\t\tString proxyDataId = environment.getProperty(\"spring.nacos.config.proxy.druid.data-id\");\n\t\treturn new NacosDruidConfigFilter(proxyDataId);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/refresh/NacosConfigRefreshEvent.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.refresh;\n\nimport org.springframework.context.ApplicationEvent;\n\npublic class NacosConfigRefreshEvent extends ApplicationEvent {\n\tString dataId;\n\tString group;\n\n\tprivate Object event;\n\n\tprivate String eventDesc;\n\n\tpublic NacosConfigRefreshEvent(Object source, Object event, String eventDesc) {\n\t\tsuper(source);\n\t\tthis.event = event;\n\t\tthis.eventDesc = eventDesc;\n\t}\n\n\tpublic Object getEvent() {\n\t\treturn this.event;\n\t}\n\n\tpublic String getEventDesc() {\n\t\treturn this.eventDesc;\n\t}\n\n\tpublic String getDataId() {\n\t\treturn dataId;\n\t}\n\n\tvoid setDataId(String dataId) {\n\t\tthis.dataId = dataId;\n\t}\n\n\tpublic String getGroup() {\n\t\treturn group;\n\t}\n\n\tvoid setGroup(String group) {\n\t\tthis.group = group;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/refresh/NacosContextRefresher.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.refresh;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport com.alibaba.cloud.nacos.NacosConfigManager;\nimport com.alibaba.cloud.nacos.NacosConfigProperties;\nimport com.alibaba.cloud.nacos.NacosPropertySourceRepository;\nimport com.alibaba.cloud.nacos.client.NacosPropertySource;\nimport com.alibaba.nacos.api.config.ConfigService;\nimport com.alibaba.nacos.api.config.listener.AbstractSharedListener;\nimport com.alibaba.nacos.api.config.listener.Listener;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.boot.context.event.ApplicationReadyEvent;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.context.ApplicationListener;\n\n/**\n * On application start up, NacosContextRefresher add nacos listeners to all application\n * level dataIds, when there is a change in the data, listeners will refresh\n * configurations.\n *\n * @author juven.xuxb\n * @author pbting\n * @author freeman\n */\npublic class NacosContextRefresher\n\t\timplements ApplicationListener<ApplicationReadyEvent>, ApplicationContextAware {\n\n\tprivate final static Logger log = LoggerFactory\n\t\t\t.getLogger(NacosContextRefresher.class);\n\n\tprivate static final AtomicLong REFRESH_COUNT = new AtomicLong(0);\n\tprivate final boolean isRefreshEnabled;\n\tprivate final NacosRefreshHistory nacosRefreshHistory;\n\tprivate NacosConfigProperties nacosConfigProperties;\n\tprivate ConfigService configService;\n\n\tprivate NacosConfigManager configManager;\n\n\tprivate ApplicationContext applicationContext;\n\n\tprivate AtomicBoolean ready = new AtomicBoolean(false);\n\n\tprivate Map<String, Listener> listenerMap = new ConcurrentHashMap<>(16);\n\n\tpublic NacosContextRefresher(NacosConfigManager nacosConfigManager,\n\t\t\tNacosRefreshHistory refreshHistory) {\n\t\tthis.configManager = nacosConfigManager;\n\t\tthis.nacosConfigProperties = nacosConfigManager.getNacosConfigProperties();\n\t\tthis.nacosRefreshHistory = refreshHistory;\n\t\tthis.isRefreshEnabled = this.nacosConfigProperties.isRefreshEnabled();\n\t}\n\n\tpublic static long getRefreshCount() {\n\t\treturn REFRESH_COUNT.get();\n\t}\n\n\tpublic static void refreshCountIncrement() {\n\t\tREFRESH_COUNT.incrementAndGet();\n\t}\n\n\t@Override\n\tpublic void onApplicationEvent(ApplicationReadyEvent event) {\n\t\t// many Spring context\n\t\tif (this.ready.compareAndSet(false, true)) {\n\t\t\tthis.registerNacosListenersForApplications();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setApplicationContext(ApplicationContext applicationContext) {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n\t/**\n\t * register Nacos Listeners.\n\t */\n\tprivate void registerNacosListenersForApplications() {\n\t\tif (isRefreshEnabled()) {\n\t\t\tfor (NacosPropertySource propertySource : NacosPropertySourceRepository\n\t\t\t\t\t.getAll()) {\n\t\t\t\tif (!propertySource.isRefreshable()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tString dataId = propertySource.getDataId();\n\t\t\t\tregisterNacosListener(propertySource.getGroup(), dataId);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void registerNacosListener(final String groupKey, final String dataKey) {\n\t\tString key = NacosPropertySourceRepository.getMapKey(dataKey, groupKey);\n\t\tListener listener = listenerMap.computeIfAbsent(key,\n\t\t\t\tlst -> new AbstractSharedListener() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void innerReceive(String dataId, String group,\n\t\t\t\t\t\t\tString configInfo) {\n\n\t\t\t\t\t\tlog.info(\"[Nacos Config] Receive Nacos config change: dataId={}, group={}\", dataKey,\n\t\t\t\t\t\t\t\tgroupKey);\n\t\t\t\t\t\trefreshCountIncrement();\n\t\t\t\t\t\tnacosRefreshHistory.addRefreshRecord(dataId, group, configInfo);\n\t\t\t\t\t\tNacosSnapshotConfigManager.putConfigSnapshot(dataId, group,\n\t\t\t\t\t\t\t\tconfigInfo);\n\t\t\t\t\t\tNacosConfigRefreshEvent event = new NacosConfigRefreshEvent(this, null, \"Refresh Nacos config\");\n\t\t\t\t\t\tevent.setDataId(dataId);\n\t\t\t\t\t\tevent.setGroup(group);\n\t\t\t\t\t\tapplicationContext.publishEvent(\n\t\t\t\t\t\t\t\tevent);\n\t\t\t\t\t\tif (log.isDebugEnabled()) {\n\t\t\t\t\t\t\tlog.debug(String.format(\n\t\t\t\t\t\t\t\t\t\"Publish Nacos config Refresh Event group=%s,dataId=%s,configInfo=%s\",\n\t\t\t\t\t\t\t\t\tgroup, dataId, configInfo));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\ttry {\n\t\t\tif (configService == null && configManager != null) {\n\t\t\t\tconfigService = configManager.getConfigService();\n\t\t\t}\n\t\t\tconfigService.addListener(dataKey, groupKey, listener);\n\t\t\tlog.info(\"[Nacos Config] Listening config: dataId={}, group={}\", dataKey,\n\t\t\t\t\tgroupKey);\n\t\t}\n\t\tcatch (NacosException e) {\n\t\t\tlog.warn(String.format(\n\t\t\t\t\t\"register fail for nacos listener ,dataId=[%s],group=[%s]\", dataKey,\n\t\t\t\t\tgroupKey), e);\n\t\t}\n\t}\n\n\tpublic NacosConfigProperties getNacosConfigProperties() {\n\t\treturn nacosConfigProperties;\n\t}\n\n\tpublic NacosContextRefresher setNacosConfigProperties(\n\t\t\tNacosConfigProperties nacosConfigProperties) {\n\t\tthis.nacosConfigProperties = nacosConfigProperties;\n\t\treturn this;\n\t}\n\n\tpublic boolean isRefreshEnabled() {\n\t\tif (null == nacosConfigProperties) {\n\t\t\treturn isRefreshEnabled;\n\t\t}\n\t\t// Compatible with older configurations\n\t\tif (nacosConfigProperties.isRefreshEnabled() && !isRefreshEnabled) {\n\t\t\treturn false;\n\t\t}\n\t\treturn isRefreshEnabled;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/refresh/NacosPropertySourceRefreshListener.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.refresh;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport com.alibaba.cloud.nacos.NacosConfigManager;\nimport com.alibaba.cloud.nacos.NacosConfigProperties;\nimport com.alibaba.cloud.nacos.client.NacosPropertySource;\nimport com.alibaba.cloud.nacos.client.NacosPropertySourceBuilder;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.config.BeanPostProcessor;\nimport org.springframework.boot.context.event.ApplicationReadyEvent;\nimport org.springframework.boot.context.properties.ConfigurationPropertiesBean;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.context.ApplicationEvent;\nimport org.springframework.context.ConfigurableApplicationContext;\nimport org.springframework.context.event.SmartApplicationListener;\nimport org.springframework.core.env.ConfigurableEnvironment;\nimport org.springframework.core.env.MutablePropertySources;\nimport org.springframework.core.env.PropertySource;\n\npublic class NacosPropertySourceRefreshListener implements BeanPostProcessor, SmartApplicationListener, ApplicationContextAware {\n\n\tprivate final static Logger log = LoggerFactory\n\t\t\t.getLogger(NacosPropertySourceRefreshListener.class);\n\n\tprivate Map<String, ConfigurationPropertiesBean> beans = new HashMap<>();\n\n\tprivate ApplicationContext applicationContext;\n\n\tprivate AtomicBoolean ready = new AtomicBoolean(false);\n\n\tNacosConfigManager nacosConfigManager;\n\n\tpublic NacosPropertySourceRefreshListener(NacosConfigManager nacosConfigManager) {\n\t\tthis.nacosConfigManager = nacosConfigManager;\n\t}\n\n\t@Override\n\tpublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {\n\n\t\tConfigurationPropertiesBean propertiesBean = ConfigurationPropertiesBean.get(this.applicationContext, bean,\n\t\t\t\tbeanName);\n\t\tif (propertiesBean != null) {\n\t\t\tthis.beans.put(beanName, propertiesBean);\n\t\t}\n\t\treturn bean;\n\t}\n\n\t@Override\n\tpublic boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {\n\t\treturn ApplicationReadyEvent.class.isAssignableFrom(eventType) || NacosConfigRefreshEvent.class.isAssignableFrom(eventType);\n\t}\n\n\t@Override\n\tpublic void setApplicationContext(ApplicationContext applicationContext) {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n\tpublic void handle(ApplicationReadyEvent event) {\n\t\tthis.ready.compareAndSet(false, true);\n\t}\n\n\t@Override\n\tpublic void onApplicationEvent(ApplicationEvent event) {\n\n\t\tif (event instanceof ApplicationReadyEvent) {\n\t\t\thandle((ApplicationReadyEvent) event);\n\t\t}\n\t\telse if (event instanceof NacosConfigRefreshEvent) {\n\t\t\thandle((NacosConfigRefreshEvent) event);\n\t\t}\n\t}\n\n\tpublic void handle(NacosConfigRefreshEvent event) {\n\t\tif (this.ready.get()) { // don't handle events before app is ready\n\t\t\tif (!applicationContext.containsBean(\"nacosConfigSpringCloudRefreshEventListener\")) {\n\t\t\t\tlog.info(\"Event received \" + event.getEventDesc());\n\n\t\t\t\tNacosPropertySourceBuilder nacosPropertySourceBuilder = new NacosPropertySourceBuilder(nacosConfigManager.getConfigService(), nacosConfigManager.getNacosConfigProperties()\n\t\t\t\t\t\t.getTimeout());\n\t\t\t\tString sourceName = String.join(NacosConfigProperties.COMMAS, event.dataId, event.group);\n\t\t\t\tConfigurableEnvironment environment = ((ConfigurableApplicationContext) applicationContext).getEnvironment();\n\t\t\t\tMutablePropertySources target = environment.getPropertySources();\n\t\t\t\tPropertySource<?> prevpropertySource = target.get(sourceName);\n\t\t\t\tif (prevpropertySource instanceof NacosPropertySource) {\n\t\t\t\t\tNacosPropertySource newProperSource = nacosPropertySourceBuilder.build(event.getDataId(), event.getGroup(), \"properties\", ((NacosPropertySource) prevpropertySource).isRefreshable());\n\t\t\t\t\ttarget.replace(sourceName, newProperSource);\n\t\t\t\t\tlog.info(\"Replace Nacos Property Source : \" + sourceName);\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/refresh/NacosRefreshHistory.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.refresh;\n\nimport java.math.BigInteger;\nimport java.nio.charset.StandardCharsets;\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\nimport java.text.DateFormat;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.LinkedList;\nimport java.util.Map;\n\nimport com.alibaba.cloud.nacos.utils.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n\npublic class NacosRefreshHistory {\n\n\tprivate final static Logger log = LoggerFactory.getLogger(NacosRefreshHistory.class);\n\n\tprivate static final int MAX_SIZE = 20;\n\n\tprivate final LinkedList<Record> records = new LinkedList<>();\n\n\tprivate final ThreadLocal<DateFormat> DATE_FORMAT = ThreadLocal\n\t\t\t.withInitial(() -> new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\"));\n\n\tprivate MessageDigest md;\n\n\tpublic NacosRefreshHistory() {\n\t\ttry {\n\t\t\tmd = MessageDigest.getInstance(\"MD5\");\n\t\t}\n\t\tcatch (NoSuchAlgorithmException e) {\n\t\t\tlog.error(\"failed to initialize MessageDigest : \", e);\n\t\t}\n\t}\n\n\t/**\n\t * recommend to use\n\t * {@link NacosRefreshHistory#addRefreshRecord(java.lang.String, java.lang.String, java.lang.String)}.\n\t * @param dataId dataId\n\t * @param md5 md5\n\t */\n\t@Deprecated\n\tpublic void add(String dataId, String md5) {\n\t\trecords.addFirst(\n\t\t\t\tnew Record(DATE_FORMAT.get().format(new Date()), dataId, \"\", md5, null));\n\t\tif (records.size() > MAX_SIZE) {\n\t\t\trecords.removeLast();\n\t\t}\n\t}\n\n\tpublic void addRefreshRecord(String dataId, String group, String data) {\n\t\trecords.addFirst(new Record(DATE_FORMAT.get().format(new Date()), dataId, group,\n\t\t\t\tmd5(data), null));\n\t\tif (records.size() > MAX_SIZE) {\n\t\t\trecords.removeLast();\n\t\t}\n\t}\n\n\tpublic LinkedList<Record> getRecords() {\n\t\treturn records;\n\t}\n\n\tprivate String md5(String data) {\n\t\tif (StringUtils.isEmpty(data)) {\n\t\t\treturn null;\n\t\t}\n\t\tif (null == md) {\n\t\t\ttry {\n\t\t\t\tmd = MessageDigest.getInstance(\"MD5\");\n\t\t\t}\n\t\t\tcatch (NoSuchAlgorithmException ignored) {\n\t\t\t\treturn \"unable to get md5\";\n\t\t\t}\n\t\t}\n\t\treturn new BigInteger(1, md.digest(data.getBytes(StandardCharsets.UTF_8)))\n\t\t\t\t.toString(16);\n\t}\n\n\tstatic class Record {\n\n\t\tprivate final String timestamp;\n\n\t\tprivate final String dataId;\n\n\t\tprivate final String group;\n\n\t\tprivate final String md5;\n\n\t\tRecord(String timestamp, String dataId, String group, String md5,\n\t\t\t\tMap<String, Object> last) {\n\t\t\tthis.timestamp = timestamp;\n\t\t\tthis.dataId = dataId;\n\t\t\tthis.group = group;\n\t\t\tthis.md5 = md5;\n\t\t}\n\n\t\tpublic String getTimestamp() {\n\t\t\treturn timestamp;\n\t\t}\n\n\t\tpublic String getDataId() {\n\t\t\treturn dataId;\n\t\t}\n\n\t\tpublic String getGroup() {\n\t\t\treturn group;\n\t\t}\n\n\t\tpublic String getMd5() {\n\t\t\treturn md5;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/refresh/NacosSnapshotConfigManager.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.refresh;\n\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * @author: ruansheng\n * @date: 2024-01-22\n */\npublic final class NacosSnapshotConfigManager {\n\n\tprivate NacosSnapshotConfigManager() {\n\t}\n\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(NacosSnapshotConfigManager.class);\n\n\tprivate static final Map<String, String> CONFIG_INFO_SNAPSHOT_MAP = new ConcurrentHashMap<>(\n\t\t\t8);\n\n\tprivate static final int MAX_SNAPSHOT_COUNT = 100;\n\n\tprivate static String formatConfigSnapshotKey(String dataId, String group) {\n\t\treturn dataId + \"@\" + group;\n\t}\n\n\tpublic static String getAndRemoveConfigSnapshot(String dataId, String group) {\n\t\tString configInfo = CONFIG_INFO_SNAPSHOT_MAP\n\t\t\t\t.get(formatConfigSnapshotKey(dataId, group));\n\t\tremoveConfigSnapshot(dataId, group);\n\t\treturn configInfo;\n\t}\n\n\tpublic static void putConfigSnapshot(String dataId, String group, String configInfo) {\n\t\ttry {\n\t\t\t// Theoretically, the capacity limit restriction will never be triggered.\n\t\t\t// This portion of the code serves as an additional fault tolerance layer.\n\t\t\tif (CONFIG_INFO_SNAPSHOT_MAP.size() > MAX_SNAPSHOT_COUNT) {\n\t\t\t\tIterator<Map.Entry<String, String>> iterator = CONFIG_INFO_SNAPSHOT_MAP\n\t\t\t\t\t\t.entrySet().iterator();\n\t\t\t\titerator.next();\n\t\t\t\titerator.remove();\n\t\t\t}\n\t\t\tString snapshotKey = formatConfigSnapshotKey(dataId, group);\n\t\t\tif (configInfo == null) {\n\t\t\t\tCONFIG_INFO_SNAPSHOT_MAP.remove(snapshotKey);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tCONFIG_INFO_SNAPSHOT_MAP.put(snapshotKey, configInfo);\n\t\t\t}\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tlog.warn(\"remove nacos config snapshot error\", e);\n\t\t}\n\t}\n\n\tpublic static void removeConfigSnapshot(String dataId, String group) {\n\t\tCONFIG_INFO_SNAPSHOT_MAP.remove(formatConfigSnapshotKey(dataId, group));\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/utils/NacosConfigUtils.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.utils;\n\n/**\n * @author zkzlx\n */\npublic final class NacosConfigUtils {\n\n\tprivate NacosConfigUtils() {\n\t}\n\n\t/**\n\t * Convert Chinese characters to Unicode.\n\t * @param configValue value of config\n\t * @return new string\n\t */\n\tpublic static String selectiveConvertUnicode(String configValue) {\n\t\tStringBuilder sb = new StringBuilder();\n\t\tchar[] chars = configValue.toCharArray();\n\t\tfor (char aChar : chars) {\n\t\t\tif (isBaseLetter(aChar)) {\n\t\t\t\tsb.append(aChar);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tsb.append(String.format(\"\\\\u%04x\", (int) aChar));\n\t\t\t}\n\t\t}\n\t\treturn sb.toString();\n\t}\n\n\t/**\n\t * char is base latin or whitespace?\n\t * @param ch a character\n\t * @return true or false\n\t */\n\tpublic static boolean isBaseLetter(char ch) {\n\t\tCharacter.UnicodeBlock ub = Character.UnicodeBlock.of(ch);\n\t\treturn ub == Character.UnicodeBlock.BASIC_LATIN || Character.isWhitespace(ch);\n\t}\n\n\t/**\n\t * char is chinese?\n\t * @param c a character\n\t * @return true or false\n\t */\n\tpublic static boolean isChinese(char c) {\n\t\tCharacter.UnicodeBlock ub = Character.UnicodeBlock.of(c);\n\t\treturn ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS\n\t\t\t\t|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS\n\t\t\t\t|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A\n\t\t\t\t|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION\n\t\t\t\t|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION\n\t\t\t\t|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/utils/PropertySourcesUtils.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.utils;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\nimport org.springframework.core.env.ConfigurableEnvironment;\nimport org.springframework.core.env.EnumerablePropertySource;\nimport org.springframework.core.env.MutablePropertySources;\nimport org.springframework.core.env.PropertyResolver;\nimport org.springframework.core.env.PropertySource;\nimport org.springframework.core.env.PropertySources;\nimport org.springframework.core.env.PropertySourcesPropertyResolver;\n\nimport static java.util.Collections.unmodifiableMap;\n\n/**\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n * @author <a href=\"mailto:yuluo08290126@gmail.com\">yuluo</a>\n * {@link PropertySources} Utilities\n * {@see PropertySources}\n */\npublic final class PropertySourcesUtils {\n\n\tprivate PropertySourcesUtils() {\n\t}\n\n\t/**\n\t * Empty String array.\n\t */\n\tpublic static final String[] EMPTY_STRING_ARRAY = {};\n\n\t/**\n\t * Get Sub {@link Properties}.\n\t *\n\t * @param propertySources {@link PropertySource} Iterable.\n\t * @param prefix          the prefix of property name.\n\t * @return Map\n\t * @see Properties\n\t */\n\tpublic static Map<String, Object> getSubProperties(Iterable<PropertySource<?>> propertySources, String prefix) {\n\n\t\tMutablePropertySources mutablePropertySources = new MutablePropertySources();\n\n\t\tfor (PropertySource<?> source : propertySources) {\n\t\t\tmutablePropertySources.addLast(source);\n\t\t}\n\n\t\treturn getSubProperties(mutablePropertySources, prefix);\n\n\t}\n\n\t/**\n\t * Get Sub {@link Properties}.\n\t *\n\t * @param environment {@link ConfigurableEnvironment}.\n\t * @param prefix      the prefix of property name.\n\t * @return Map\n\t * @see Properties\n\t */\n\tpublic static Map<String, Object> getSubProperties(ConfigurableEnvironment environment, String prefix) {\n\n\t\treturn getSubProperties(environment.getPropertySources(), environment, prefix);\n\t}\n\n\t/**\n\t * Normalize the prefix.\n\t *\n\t * @param prefix the prefix.\n\t * @return the prefix.\n\t */\n\tpublic static String normalizePrefix(String prefix) {\n\t\treturn prefix.endsWith(\".\") ? prefix : prefix + \".\";\n\t}\n\n\t/**\n\t * Get prefixed {@link Properties}.\n\t *\n\t * @param propertySources {@link PropertySources}.\n\t * @param prefix          the prefix of property name.\n\t * @return Map\n\t * @see Properties\n\t */\n\tpublic static Map<String, Object> getSubProperties(PropertySources propertySources, String prefix) {\n\n\t\treturn getSubProperties(propertySources, new PropertySourcesPropertyResolver(propertySources), prefix);\n\t}\n\n\t/**\n\t * Get prefixed {@link Properties}.\n\t *\n\t * @param propertySources  {@link PropertySources}.\n\t * @param propertyResolver {@link PropertyResolver} to resolve the placeholder if present.\n\t * @param prefix           the prefix of property name.\n\t * @return Map\n\t * @see Properties\n\t */\n\tpublic static Map<String, Object> getSubProperties(PropertySources propertySources, PropertyResolver propertyResolver, String prefix) {\n\n\t\tMap<String, Object> subProperties = new LinkedHashMap<String, Object>();\n\n\t\tString normalizedPrefix = normalizePrefix(prefix);\n\n\t\tfor (PropertySource<?> source : propertySources) {\n\t\t\tfor (String name : getPropertyNames(source)) {\n\t\t\t\tif (!subProperties.containsKey(name) && name.startsWith(normalizedPrefix)) {\n\t\t\t\t\tString subName = name.substring(normalizedPrefix.length());\n\t\t\t\t\tif (!subProperties.containsKey(subName)) { // take first one\n\t\t\t\t\t\tObject value = source.getProperty(name);\n\t\t\t\t\t\tif (value instanceof String) {\n\t\t\t\t\t\t\t// Resolve placeholder\n\t\t\t\t\t\t\tvalue = propertyResolver.resolvePlaceholders((String) value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsubProperties.put(subName, value);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn unmodifiableMap(subProperties);\n\t}\n\n\t/**\n\t * Get the property names as the array from the specified {@link PropertySource} instance.\n\t *\n\t * @param propertySource {@link PropertySource} instance.\n\t * @return non-null\n\t */\n\tpublic static String[] getPropertyNames(PropertySource propertySource) {\n\n\t\tString[] propertyNames = propertySource instanceof EnumerablePropertySource ?\n\t\t\t\t((EnumerablePropertySource<?>) propertySource).getPropertyNames() : null;\n\n\t\tif (propertyNames == null) {\n\t\t\tpropertyNames = EMPTY_STRING_ARRAY;\n\t\t}\n\n\t\treturn propertyNames;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/utils/StringUtils.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.utils;\n\n/**\n * StringUtils. copy from apache common-lang3.\n *\n * @author <a href=\"mailto:chenxilzx1@gmail.com\">theonefx</a>\n */\npublic final class StringUtils {\n\n\t/**\n\t * The empty String {@code \"\"}.\n\t *\n\t * @since 2.0\n\t */\n\tpublic static final String EMPTY = \"\";\n\n\t/**\n\t * Represents a failed index search.\n\t * @since 2.1\n\t */\n\tpublic static final int INDEX_NOT_FOUND = -1;\n\n\tprivate StringUtils() {\n\t}\n\n\t/**\n\t * <p>\n\t * Checks if a CharSequence is empty (\"\") or null.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.isEmpty(null)      = true\n\t * StringUtils.isEmpty(\"\")        = true\n\t * StringUtils.isEmpty(\" \")       = false\n\t * StringUtils.isEmpty(\"bob\")     = false\n\t * StringUtils.isEmpty(\"  bob  \") = false\n\t * </pre>\n\t *\n\t * <p>\n\t * NOTE: This method changed in Lang version 2.0. It no longer trims the CharSequence.\n\t * That functionality is available in isBlank().\n\t * </p>\n\t * @param cs the CharSequence to check, may be null\n\t * @return {@code true} if the CharSequence is empty or null\n\t * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)\n\t */\n\tpublic static boolean isEmpty(final CharSequence cs) {\n\t\treturn cs == null || cs.length() == 0;\n\t}\n\n\t/**\n\t * <p>\n\t * Checks if a CharSequence is not empty (\"\") and not null.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.isNotEmpty(null)      = false\n\t * StringUtils.isNotEmpty(\"\")        = false\n\t * StringUtils.isNotEmpty(\" \")       = true\n\t * StringUtils.isNotEmpty(\"bob\")     = true\n\t * StringUtils.isNotEmpty(\"  bob  \") = true\n\t * </pre>\n\t * @param cs the CharSequence to check, may be null\n\t * @return {@code true} if the CharSequence is not empty and not null\n\t * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence)\n\t */\n\tpublic static boolean isNotEmpty(final CharSequence cs) {\n\t\treturn !isEmpty(cs);\n\t}\n\n\t/**\n\t * <p>\n\t * Checks if a CharSequence is whitespace, empty (\"\") or null.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.isBlank(null)      = true\n\t * StringUtils.isBlank(\"\")        = true\n\t * StringUtils.isBlank(\" \")       = true\n\t * StringUtils.isBlank(\"bob\")     = false\n\t * StringUtils.isBlank(\"  bob  \") = false\n\t * </pre>\n\t * @param cs the CharSequence to check, may be null\n\t * @return {@code true} if the CharSequence is null, empty or whitespace\n\t */\n\tpublic static boolean isBlank(final CharSequence cs) {\n\t\tif (cs == null || cs.length() == 0) {\n\t\t\treturn true;\n\t\t}\n\t\tint strLen = cs.length();\n\t\tfor (int i = 0; i < strLen; i++) {\n\t\t\tif (!Character.isWhitespace(cs.charAt(i))) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * <p>\n\t * Checks if a CharSequence is not empty (\"\"), not null and not whitespace only.\n\t * </p>\n\t *\n\t * <p>\n\t * Whitespace is defined by {@link Character#isWhitespace(char)}.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.isNotBlank(null)      = false\n\t * StringUtils.isNotBlank(\"\")        = false\n\t * StringUtils.isNotBlank(\" \")       = false\n\t * StringUtils.isNotBlank(\"bob\")     = true\n\t * StringUtils.isNotBlank(\"  bob  \") = true\n\t * </pre>\n\t * @param cs the CharSequence to check, may be null\n\t * @return {@code true} if the CharSequence is not empty and not null and not\n\t * whitespace only\n\t * @since 2.0\n\t * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence)\n\t */\n\tpublic static boolean isNotBlank(final CharSequence cs) {\n\t\treturn !isBlank(cs);\n\t}\n\n\t// Trim\n\t// -----------------------------------------------------------------------\n\n\t/**\n\t * <p>\n\t * Removes control characters (char &lt;= 32) from both ends of this String, handling\n\t * {@code null} by returning {@code null}.\n\t * </p>\n\t *\n\t * <p>\n\t * The String is trimmed using {@link String#trim()}. Trim removes start and end\n\t * characters &lt;= 32.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.trim(null)          = null\n\t * StringUtils.trim(\"\")            = \"\"\n\t * StringUtils.trim(\"     \")       = \"\"\n\t * StringUtils.trim(\"abc\")         = \"abc\"\n\t * StringUtils.trim(\"    abc    \") = \"abc\"\n\t * </pre>\n\t * @param str the String to be trimmed, may be null\n\t * @return the trimmed string, {@code null} if null String input\n\t */\n\tpublic static String trim(final String str) {\n\t\treturn str == null ? null : str.trim();\n\t}\n\n\t// Equals\n\t// -----------------------------------------------------------------------\n\n\t/**\n\t * <p>\n\t * Compares two CharSequences, returning {@code true} if they represent equal\n\t * sequences of characters.\n\t * </p>\n\t *\n\t * <p>\n\t * {@code null}s are handled without exceptions. Two {@code null} references are\n\t * considered to be equal. The comparison is case sensitive.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.equals(null, null)   = true\n\t * StringUtils.equals(null, \"abc\")  = false\n\t * StringUtils.equals(\"abc\", null)  = false\n\t * StringUtils.equals(\"abc\", \"abc\") = true\n\t * StringUtils.equals(\"abc\", \"ABC\") = false\n\t * </pre>\n\t * @param cs1 the first CharSequence, may be {@code null}\n\t * @param cs2 the second CharSequence, may be {@code null}\n\t * @return {@code true} if the CharSequences are equal (case-sensitive), or both\n\t * {@code null}\n\t * @see Object#equals(Object)\n\t */\n\tpublic static boolean equals(final CharSequence cs1, final CharSequence cs2) {\n\t\tif (cs1 == cs2) {\n\t\t\treturn true;\n\t\t}\n\t\tif (cs1 == null || cs2 == null) {\n\t\t\treturn false;\n\t\t}\n\t\tif (cs1 instanceof String && cs2 instanceof String) {\n\t\t\treturn cs1.equals(cs2);\n\t\t}\n\t\treturn StringUtils.regionMatches(cs1, false, 0, cs2, 0,\n\t\t\t\tMath.max(cs1.length(), cs2.length()));\n\t}\n\n\t/**\n\t * Green implementation of regionMatches.\n\t * @param cs the {@code CharSequence} to be processed\n\t * @param ignoreCase whether or not to be case insensitive\n\t * @param thisStart the index to start on the {@code cs} CharSequence\n\t * @param substring the {@code CharSequence} to be looked for\n\t * @param start the index to start on the {@code substring} CharSequence\n\t * @param length character length of the region\n\t * @return whether the region matched\n\t */\n\tpublic static boolean regionMatches(final CharSequence cs, final boolean ignoreCase,\n\t\t\tfinal int thisStart, final CharSequence substring, final int start,\n\t\t\tfinal int length) {\n\t\tif (cs instanceof String && substring instanceof String) {\n\t\t\treturn ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring,\n\t\t\t\t\tstart, length);\n\t\t}\n\t\tint index1 = thisStart;\n\t\tint index2 = start;\n\t\tint tmpLen = length;\n\n\t\twhile (tmpLen-- > 0) {\n\t\t\tfinal char c1 = cs.charAt(index1++);\n\t\t\tfinal char c2 = substring.charAt(index2++);\n\n\t\t\tif (c1 == c2) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!ignoreCase) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// The same check as in String.regionMatches():\n\t\t\tif (Character.toUpperCase(c1) != Character.toUpperCase(c2)\n\t\t\t\t\t&& Character.toLowerCase(c1) != Character.toLowerCase(c2)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * <p>\n\t * Gets the substring after the first occurrence of a separator. The separator is not\n\t * returned.\n\t * </p>\n\t *\n\t * <p>\n\t * A <code>null</code> string input will return <code>null</code>. An empty (\"\")\n\t * string input will return the empty string. A <code>null</code> separator will\n\t * return the empty string if the input string is not <code>null</code>.\n\t * </p>\n\t *\n\t * <p>\n\t * If nothing is found, the empty string is returned.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.substringAfter(null, *)      = null\n\t * StringUtils.substringAfter(\"\", *)        = \"\"\n\t * StringUtils.substringAfter(*, null)      = \"\"\n\t * StringUtils.substringAfter(\"abc\", \"a\")   = \"bc\"\n\t * StringUtils.substringAfter(\"abcba\", \"b\") = \"cba\"\n\t * StringUtils.substringAfter(\"abc\", \"c\")   = \"\"\n\t * StringUtils.substringAfter(\"abc\", \"d\")   = \"\"\n\t * StringUtils.substringAfter(\"abc\", \"\")    = \"abc\"\n\t * </pre>\n\t * @param str the String to get a substring from, may be null\n\t * @param separator the String to search for, may be null\n\t * @return the substring after the first occurrence of the separator,\n\t * <code>null</code> if null String input\n\t * @since 2.0\n\t */\n\tpublic static String substringAfter(String str, String separator) {\n\t\tif (isEmpty(str)) {\n\t\t\treturn str;\n\t\t}\n\t\tif (separator == null) {\n\t\t\treturn EMPTY;\n\t\t}\n\t\tint pos = str.indexOf(separator);\n\t\tif (pos == INDEX_NOT_FOUND) {\n\t\t\treturn EMPTY;\n\t\t}\n\t\treturn str.substring(pos + separator.length());\n\t}\n\n\t// Substring between\n\t// -----------------------------------------------------------------------\n\t/**\n\t * <p>\n\t * Gets the String that is nested in between two instances of the same String.\n\t * </p>\n\t *\n\t * <p>\n\t * A <code>null</code> input String returns <code>null</code>. A <code>null</code> tag\n\t * returns <code>null</code>.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.substringBetween(null, *)            = null\n\t * StringUtils.substringBetween(\"\", \"\")             = \"\"\n\t * StringUtils.substringBetween(\"\", \"tag\")          = null\n\t * StringUtils.substringBetween(\"tagabctag\", null)  = null\n\t * StringUtils.substringBetween(\"tagabctag\", \"\")    = \"\"\n\t * StringUtils.substringBetween(\"tagabctag\", \"tag\") = \"abc\"\n\t * </pre>\n\t * @param str the String containing the substring, may be null\n\t * @param tag the String before and after the substring, may be null\n\t * @return the substring, <code>null</code> if no match\n\t * @since 2.0\n\t */\n\tpublic static String substringBetween(String str, String tag) {\n\t\treturn substringBetween(str, tag, tag);\n\t}\n\n\t/**\n\t * <p>\n\t * Gets the String that is nested in between two Strings. Only the first match is\n\t * returned.\n\t * </p>\n\t *\n\t * <p>\n\t * A <code>null</code> input String returns <code>null</code>. A <code>null</code>\n\t * open/close returns <code>null</code> (no match). An empty (\"\") open and close\n\t * returns an empty string.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.substringBetween(\"wx[b]yz\", \"[\", \"]\") = \"b\"\n\t * StringUtils.substringBetween(null, *, *)          = null\n\t * StringUtils.substringBetween(*, null, *)          = null\n\t * StringUtils.substringBetween(*, *, null)          = null\n\t * StringUtils.substringBetween(\"\", \"\", \"\")          = \"\"\n\t * StringUtils.substringBetween(\"\", \"\", \"]\")         = null\n\t * StringUtils.substringBetween(\"\", \"[\", \"]\")        = null\n\t * StringUtils.substringBetween(\"yabcz\", \"\", \"\")     = \"\"\n\t * StringUtils.substringBetween(\"yabcz\", \"y\", \"z\")   = \"abc\"\n\t * StringUtils.substringBetween(\"yabczyabcz\", \"y\", \"z\")   = \"abc\"\n\t * </pre>\n\t * @param str the String containing the substring, may be null\n\t * @param open the String before the substring, may be null\n\t * @param close the String after the substring, may be null\n\t * @return the substring, <code>null</code> if no match\n\t * @since 2.0\n\t */\n\tpublic static String substringBetween(String str, String open, String close) {\n\t\tif (str == null || open == null || close == null) {\n\t\t\treturn null;\n\t\t}\n\t\tint start = str.indexOf(open);\n\t\tif (start != INDEX_NOT_FOUND) {\n\t\t\tint end = str.indexOf(close, start + open.length());\n\t\t\tif (end != INDEX_NOT_FOUND) {\n\t\t\t\treturn str.substring(start + open.length(), end);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json",
    "content": "{\n  \"properties\": [\n    {\n      \"name\": \"spring.nacos.server-addr\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"127.0.0.1:8848\",\n      \"description\": \"nacos server address.\"\n    },\n    {\n      \"name\": \"spring.nacos.config.server-addr\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"${spring.nacos.server-addr}\",\n      \"description\": \"nacos config server address.\"\n    },\n    {\n      \"name\": \"spring.nacos.config.encode\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"UTF-8\",\n      \"description\": \"default encode for nacos config content.\"\n    },\n    {\n      \"name\": \"spring.nacos.config.prefix\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"${spring.application.name}\",\n      \"description\": \"the prefix of dataId, nacos config data meta info. dataId = prefix + '-' + ${spring.active.profile} + `.` + ${spring.cloud.nacos.config.file-extension}.\"\n    },\n    {\n      \"name\": \"spring.nacos.config.file-extension\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"properties\",\n      \"description\": \"the suffix of nacos config dataId, also the file extension of config content, only support properties now.\"\n    },\n    {\n      \"name\": \"spring.nacos.config.shared-dataids\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"the dataids for configurable multiple shared configurations , multiple separated by commas .\"\n    },\n    {\n      \"name\": \"spring.nacos.config.shared-configs\",\n      \"type\": \"java.util.List\",\n      \"description\": \"a set of shared configurations .e.g: spring.cloud.nacos.config.shared-configs[0]=xxx .\"\n    },\n    {\n      \"name\": \"spring.nacos.config.refreshable-dataids\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"refreshable dataids , multiple separated by commas .Not providing support,the need to refresh is specified by the respective refresh configuration.\"\n    },\n    {\n      \"name\": \"spring.nacos.config.ext-config\",\n      \"type\": \"java.util.List\",\n      \"description\": \"a set of extended configurations .\"\n    },\n    {\n      \"name\": \"spring.nacos.config.extension-configs\",\n      \"type\": \"java.util.List\",\n      \"description\": \"a set of extensional configurations .e.g: spring.cloud.nacos.config.extension-configs[0]=xxx .\"\n    },\n    {\n      \"name\": \"spring.nacos.config.refresh-enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": true,\n      \"description\": \"the master switch for refresh configuration, it default opened(true).\"\n    },\n    {\n      \"name\": \"spring.nacos.config.enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": true,\n      \"description\": \"enable nacos config or not.\"\n    },\n    {\n      \"name\": \"spring.nacos.config.username\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"${spring.nacos.username}\",\n      \"description\": \"nacos config service's userName to authenticate.\"\n    },\n    {\n      \"name\": \"spring.nacos.config.import-check.enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": true,\n      \"description\": \"Whether to enable import-check.\"\n    },\n    {\n      \"name\": \"spring.nacos.config.password\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"${spring.nacos.password}\",\n      \"description\": \"nacos config service's password to authenticate.\"\n    },\n    {\n      \"name\": \"spring.nacos.username\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"nacos userName to authenticate.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.password\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"nacos password to authenticate.\"\n    },\n    {\n      \"name\": \"spring.nacos.config.preference\",\n      \"type\": \"com.alibaba.cloud.nacos.configdata.ConfigPreference\",\n      \"defaultValue\": \"local\",\n      \"description\": \"Config preference.\"\n    },\n    {\n      \"name\": \"spring.nacos.config.health-indicator.enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": false,\n      \"description\": \"whether to enable nacos-config health indicator.\"\n    }\n  ]\n}"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/resources/META-INF/native-image/reflect-config.json",
    "content": "[\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcConnection\"\n    },\n    \"name\": \"com.alibaba.nacos.api.ability.ClientAbilities\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"getConfigAbility\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getNamingAbility\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getRemoteAbility\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcConnection\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.ability.ClientConfigAbility\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"isSupportRemoteMetrics\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.request.AbstractConfigRequest\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.RpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.request.AbstractConfigRequest\",\n    \"methods\": [\n      {\n        \"name\": \"getModule\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.gson.Gson\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.request.AbstractConfigRequest\",\n    \"allDeclaredFields\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.boot.support.EnvironmentPostProcessorApplicationListener\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.request.AbstractConfigRequest\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getConfigListenContexts\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isListen\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.gson.internal.bind.CollectionTypeAdapterFactory\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest$ConfigListenContext\",\n    \"allDeclaredFields\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.fasterxml.jackson.databind.SerializerProvider\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest$ConfigListenContext\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest$ConfigListenContext\",\n    \"methods\": [\n      {\n        \"name\": \"getDataId\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getGroup\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getMd5\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTenant\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient$1\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.request.ConfigChangeNotifyRequest\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setDataId\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setGroup\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest\",\n    \"allDeclaredFields\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getDataId\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getGroup\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTag\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTenant\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isNotify\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.boot.support.EnvironmentPostProcessorApplicationListener\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest\",\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setChangedConfigs\",\n        \"parameterTypes\": [\n          \"java.util.List\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.fasterxml.jackson.databind.DeserializationContext\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse$ConfigContext\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.fasterxml.jackson.databind.deser.std.CollectionDeserializer\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse$ConfigContext\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setDataId\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setGroup\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setTenant\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcUtils\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.response.ConfigChangeNotifyResponse\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setBeta\",\n        \"parameterTypes\": [\n          \"boolean\"\n        ]\n      },\n      {\n        \"name\": \"setContent\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setContentType\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setLastModified\",\n        \"parameterTypes\": [\n          \"long\"\n        ]\n      },\n      {\n        \"name\": \"setMd5\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.boot.support.EnvironmentPostProcessorApplicationListener\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.api.grpc.auto.Metadata\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Metadata\",\n    \"methods\": [\n      {\n        \"name\": \"getClientIp\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getClientIpBytes\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getType\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTypeBytes\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.GeneratedMessageV3$FieldAccessorTable$MapFieldAccessor\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Metadata\",\n    \"methods\": [\n      {\n        \"name\": \"getDefaultInstance\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.GeneratedMessageV3$FieldAccessorTable$SingularMessageFieldAccessor\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Metadata\",\n    \"methods\": [\n      {\n        \"name\": \"newBuilder\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.TextFormat$Printer\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Metadata\",\n    \"methods\": [\n      {\n        \"name\": \"getClientIp\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getType\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.api.grpc.auto.Metadata\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Metadata$Builder\",\n    \"methods\": [\n      {\n        \"name\": \"clearClientIp\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"clearType\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getClientIp\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getClientIpBytes\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getType\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTypeBytes\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setClientIp\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setClientIpBytes\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.com.google.protobuf.ByteString\"\n        ]\n      },\n      {\n        \"name\": \"setType\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setTypeBytes\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.com.google.protobuf.ByteString\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.GeneratedMessageV3$FieldAccessorTable$SingularFieldAccessor$ReflectionInvoker\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Payload\",\n    \"methods\": [\n      {\n        \"name\": \"hasBody\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"hasMetadata\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.GeneratedMessageV3$FieldAccessorTable$SingularMessageFieldAccessor\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Payload\",\n    \"methods\": [\n      {\n        \"name\": \"getBody\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getMetadata\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"hasBody\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"hasMetadata\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.TextFormat$Printer\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Payload\",\n    \"methods\": [\n      {\n        \"name\": \"getBody\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getMetadata\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.GeneratedMessageV3$FieldAccessorTable$SingularMessageFieldAccessor\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Payload$Builder\",\n    \"methods\": [\n      {\n        \"name\": \"clearBody\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"clearMetadata\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getBody\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getBodyBuilder\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getMetadata\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getMetadataBuilder\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"hasBody\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"hasMetadata\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setBody\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.com.google.protobuf.Any\"\n        ]\n      },\n      {\n        \"name\": \"setMetadata\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.api.grpc.auto.Metadata\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcConnection\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.ability.ClientNamingAbility\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"isSupportDeltaPush\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isSupportRemoteMetric\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.Payload\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.RpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.Payload\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.Payload\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient$1\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.Payload\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcConnection\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.Payload\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcUtils\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.Payload\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.fasterxml.jackson.databind.DeserializationContext\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.Payload\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.fasterxml.jackson.databind.ObjectMapper\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.Payload\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.boot.support.EnvironmentPostProcessorApplicationListener\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.Payload\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcConnection\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.ability.ClientRemoteAbility\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"isSupportRemoteConnection\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcConnection\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.ConnectionSetupRequest\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"getAbilities\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getClientVersion\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getLabels\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTenant\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.RpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.HealthCheckRequest\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.RpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.InternalRequest\",\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"getModule\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.InternalRequest\",\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"getModule\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcConnection\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.InternalRequest\",\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"getModule\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.Request\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.RpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.Request\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.Request\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient$1\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.Request\",\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"setRequestId\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcConnection\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.Request\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcUtils\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.Request\",\n    \"methods\": [\n      {\n        \"name\": \"getHeaders\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getRequestId\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.gson.Gson\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.Request\",\n    \"allDeclaredFields\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.boot.support.EnvironmentPostProcessorApplicationListener\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.Request\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.ServerCheckRequest\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient$1\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.ServerRequest\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.RpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.response.HealthCheckResponse\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.response.Response\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.RpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.response.Response\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.response.Response\",\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"setErrorCode\",\n        \"parameterTypes\": [\n          \"int\"\n        ]\n      },\n      {\n        \"name\": \"setResultCode\",\n        \"parameterTypes\": [\n          \"int\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcConnection\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.response.Response\",\n    \"methods\": [\n      {\n        \"name\": \"setErrorCode\",\n        \"parameterTypes\": [\n          \"int\"\n        ]\n      },\n      {\n        \"name\": \"setResultCode\",\n        \"parameterTypes\": [\n          \"int\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcUtils\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.response.Response\",\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"getErrorCode\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getMessage\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getRequestId\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getResultCode\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isSuccess\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.boot.support.EnvironmentPostProcessorApplicationListener\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.response.Response\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.response.ServerCheckResponse\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setConnectionId\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.api.config.ConfigFactory\"\n    },\n    \"name\": \"com.alibaba.nacos.client.config.NacosConfigService\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": [\n          \"java.util.Properties\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.spi.NacosServiceLoader\"\n    },\n    \"name\": \"com.alibaba.nacos.client.logging.logback.NacosLogbackConfiguratorAdapterV1\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.fasterxml.jackson.databind.ObjectMapper\"\n    },\n    \"name\": \"com.alibaba.nacos.common.remote.TlsConfig\",\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"getCertChainFile\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getCertPrivateKey\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getCertPrivateKeyPassword\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getCiphers\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getEnableTls\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getMutualAuthEnable\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getProtocols\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getSslProvider\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTrustAll\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTrustCollectionCertFile\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.fasterxml.jackson.databind.ObjectMapper\"\n    },\n    \"name\": \"com.alibaba.nacos.common.remote.client.RpcClientTlsConfig\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.com.google.common.util.concurrent.AbstractFuture\",\n    \"fields\": [\n      {\n        \"name\": \"listeners\"\n      },\n      {\n        \"name\": \"value\"\n      },\n      {\n        \"name\": \"waiters\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.com.google.common.util.concurrent.AbstractFuture$Waiter\",\n    \"fields\": [\n      {\n        \"name\": \"next\"\n      },\n      {\n        \"name\": \"thread\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.Any\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.com.google.protobuf.Any\",\n    \"methods\": [\n      {\n        \"name\": \"getTypeUrl\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTypeUrlBytes\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getValue\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.GeneratedMessageV3$FieldAccessorTable$SingularMessageFieldAccessor\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.com.google.protobuf.Any\",\n    \"methods\": [\n      {\n        \"name\": \"newBuilder\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.TextFormat$Printer\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.com.google.protobuf.Any\",\n    \"methods\": [\n      {\n        \"name\": \"getTypeUrl\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getValue\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.Any\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.com.google.protobuf.Any$Builder\",\n    \"methods\": [\n      {\n        \"name\": \"clearTypeUrl\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"clearValue\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTypeUrl\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTypeUrlBytes\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getValue\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setTypeUrl\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setTypeUrlBytes\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.com.google.protobuf.ByteString\"\n        ]\n      },\n      {\n        \"name\": \"setValue\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.com.google.protobuf.ByteString\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.ExtensionRegistryFactory\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.com.google.protobuf.ExtensionRegistry\",\n    \"methods\": [\n      {\n        \"name\": \"getEmptyRegistry\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.NameResolverRegistry\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.internal.DnsNameResolverProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.LoadBalancerRegistry\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.internal.PickFirstLoadBalancerProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$GrpcNegotiationHandler\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.AbstractNettyHandler\",\n    \"methods\": [\n      {\n        \"name\": \"channelActive\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"exceptionCaught\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Throwable\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$GrpcNegotiationHandler\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler\",\n    \"methods\": [\n      {\n        \"name\": \"channelInactive\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"close\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"write\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$ProtocolNegotiationHandler\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$GrpcNegotiationHandler\",\n    \"methods\": [\n      {\n        \"name\": \"userEventTriggered\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$ProtocolNegotiationHandler\",\n    \"methods\": [\n      {\n        \"name\": \"userEventTriggered\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$WaitUntilActiveHandler\",\n    \"methods\": [\n      {\n        \"name\": \"channelActive\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.WriteBufferingAndExceptionHandler\",\n    \"methods\": [\n      {\n        \"name\": \"channelInactive\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelRead\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\"\n        ]\n      },\n      {\n        \"name\": \"close\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"connect\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.net.SocketAddress\",\n          \"java.net.SocketAddress\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"exceptionCaught\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Throwable\"\n        ]\n      },\n      {\n        \"name\": \"flush\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"write\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.buffer.AbstractByteBufAllocator\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.buffer.AbstractByteBufAllocator\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.ReferenceCountUpdater\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.buffer.AbstractReferenceCountedByteBuf\",\n    \"fields\": [\n      {\n        \"name\": \"refCnt\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelDuplexHandler\",\n    \"methods\": [\n      {\n        \"name\": \"bind\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.net.SocketAddress\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"close\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"connect\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.net.SocketAddress\",\n          \"java.net.SocketAddress\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"deregister\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"disconnect\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"flush\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"read\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"write\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$ProtocolNegotiationHandler\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelInboundHandlerAdapter\",\n    \"methods\": [\n      {\n        \"name\": \"channelActive\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelInactive\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelRead\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\"\n        ]\n      },\n      {\n        \"name\": \"channelReadComplete\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelWritabilityChanged\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"exceptionCaught\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Throwable\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.DefaultChannelHandlerContext\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelInboundHandlerAdapter\",\n    \"methods\": [\n      {\n        \"name\": \"channelRegistered\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelUnregistered\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelInboundHandlerAdapter\",\n    \"methods\": [\n      {\n        \"name\": \"channelActive\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelInactive\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelRead\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\"\n        ]\n      },\n      {\n        \"name\": \"channelReadComplete\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelWritabilityChanged\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"exceptionCaught\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Throwable\"\n        ]\n      },\n      {\n        \"name\": \"userEventTriggered\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline$HeadContext\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline$HeadContext\",\n    \"methods\": [\n      {\n        \"name\": \"bind\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.net.SocketAddress\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"channelActive\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelInactive\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelRead\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\"\n        ]\n      },\n      {\n        \"name\": \"channelReadComplete\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelRegistered\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelUnregistered\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelWritabilityChanged\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"close\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"connect\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.net.SocketAddress\",\n          \"java.net.SocketAddress\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"deregister\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"disconnect\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"exceptionCaught\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Throwable\"\n        ]\n      },\n      {\n        \"name\": \"flush\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"read\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"userEventTriggered\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\"\n        ]\n      },\n      {\n        \"name\": \"write\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline$TailContext\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline$TailContext\",\n    \"methods\": [\n      {\n        \"name\": \"channelActive\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelInactive\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelRead\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\"\n        ]\n      },\n      {\n        \"name\": \"channelReadComplete\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelRegistered\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelUnregistered\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelWritabilityChanged\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"exceptionCaught\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Throwable\"\n        ]\n      },\n      {\n        \"name\": \"userEventTriggered\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ReflectiveChannelFactory\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.socket.nio.NioSocketChannel\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$GrpcNegotiationHandler\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.handler.codec.ByteToMessageDecoder\",\n    \"methods\": [\n      {\n        \"name\": \"channelRead\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\"\n        ]\n      },\n      {\n        \"name\": \"userEventTriggered\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$GrpcNegotiationHandler\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler\",\n    \"methods\": [\n      {\n        \"name\": \"bind\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.net.SocketAddress\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"channelReadComplete\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelWritabilityChanged\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"connect\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"java.net.SocketAddress\",\n          \"java.net.SocketAddress\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"deregister\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"disconnect\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"flush\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"read\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.ReferenceCountUtil\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.ReferenceCountUtil\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields\",\n    \"fields\": [\n      {\n        \"name\": \"producerLimit\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields\",\n    \"fields\": [\n      {\n        \"name\": \"consumerIndex\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields\",\n    \"fields\": [\n      {\n        \"name\": \"producerIndex\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField\",\n    \"fields\": [\n      {\n        \"name\": \"consumerIndex\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField\",\n    \"fields\": [\n      {\n        \"name\": \"producerIndex\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField\",\n    \"fields\": [\n      {\n        \"name\": \"producerLimit\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.LoadBalancerRegistry\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.util.SecretRoundRobinLoadBalancerProvider$Provider\"\n  },\n  {\n    \"name\": \"com.alibaba.nacos.api.naming.pojo.Instance\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getClusterName\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getInstanceHeartBeatInterval\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getInstanceHeartBeatTimeOut\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getInstanceId\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getInstanceIdGenerator\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getIp\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getIpDeleteTimeout\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getMetadata\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getPort\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getServiceName\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getWeight\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isEnabled\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isEphemeral\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isHealthy\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setClusterName\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setEnabled\",\n        \"parameterTypes\": [\n          \"boolean\"\n        ]\n      },\n      {\n        \"name\": \"setEphemeral\",\n        \"parameterTypes\": [\n          \"boolean\"\n        ]\n      },\n      {\n        \"name\": \"setHealthy\",\n        \"parameterTypes\": [\n          \"boolean\"\n        ]\n      },\n      {\n        \"name\": \"setInstanceId\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setIp\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setMetadata\",\n        \"parameterTypes\": [\n          \"java.util.Map\"\n        ]\n      },\n      {\n        \"name\": \"setPort\",\n        \"parameterTypes\": [\n          \"int\"\n        ]\n      },\n      {\n        \"name\": \"setServiceName\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setWeight\",\n        \"parameterTypes\": [\n          \"double\"\n        ]\n      }\n    ]\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/resources/META-INF/native-image/resource-config.json",
    "content": "{\n  \"resources\": {\n    \"includes\": [\n      {\n        \"condition\": {\n          \"typeReachable\": \"com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.api.config.filter.IConfigFilter\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"com.alibaba.nacos.common.remote.PayloadRegistry\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.api.remote.Payload\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"com.alibaba.nacos.client.utils.LogUtils\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.common.log.NacosLogbackConfigurator\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"com.alibaba.nacos.plugin.auth.spi.client.ClientAuthPluginManager\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.plugin.auth.spi.client.AbstractClientAuthService\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.LoadBalancerRegistry\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.shaded.io.grpc.LoadBalancerProvider\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.ManagedChannelRegistry\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.shaded.io.grpc.ManagedChannelProvider\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.NameResolverRegistry\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.shaded.io.grpc.NameResolverProvider\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"com.alibaba.nacos.common.utils.VersionUtils\"\n        },\n        \"pattern\": \"\\\\Qnacos-version.txt\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"com.alibaba.nacos.common.utils.ResourceUtils\"\n        },\n        \"pattern\": \"\\\\Qnacos_default_setting.properties\\\\E\"\n      }\n    ]\n  },\n  \"bundles\": []\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/resources/META-INF/services/com.alibaba.nacos.api.config.listener.ConfigChangeParser",
    "content": "com.alibaba.cloud.nacos.annotation.ScaYamlConfigChangeParser"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports",
    "content": "com.alibaba.cloud.nacos.NacosConfigAutoConfiguration\ncom.alibaba.cloud.nacos.endpoint.NacosConfigEndpointAutoConfiguration\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/main/resources/META-INF/spring.factories",
    "content": "org.springframework.boot.diagnostics.FailureAnalyzer=\\\ncom.alibaba.cloud.nacos.diagnostics.analyzer.NacosConnectionFailureAnalyzer\norg.springframework.boot.env.PropertySourceLoader=\\\ncom.alibaba.cloud.nacos.parser.NacosJsonPropertySourceLoader,\\\ncom.alibaba.cloud.nacos.parser.NacosXmlPropertySourceLoader\n\n# ConfigData Location Resolvers\norg.springframework.boot.context.config.ConfigDataLocationResolver=\\\ncom.alibaba.cloud.nacos.configdata.NacosConfigDataLocationResolver\n\n# ConfigData Loaders\norg.springframework.boot.context.config.ConfigDataLoader=\\\ncom.alibaba.cloud.nacos.configdata.NacosConfigDataLoader\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/annotation/NacosPropertiesKeyListenerTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.annotation;\n\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport com.alibaba.nacos.api.config.ConfigChangeEvent;\nimport com.alibaba.nacos.api.config.ConfigChangeItem;\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * Tests for {@link NacosPropertiesKeyListener} array key matching.\n *\n * @see <a href=\"https://github.com/alibaba/spring-cloud-alibaba/issues/4239\">#4239</a>\n */\nclass NacosPropertiesKeyListenerTest {\n\n\t@Test\n\tvoid exactKeyMatch() {\n\t\tAtomicBoolean called = new AtomicBoolean(false);\n\t\tNacosPropertiesKeyListener listener = createListener(called, Set.of(\"myKey\"), Set.of());\n\n\t\tlistener.receiveConfigChange(buildEvent(\"myKey\"));\n\n\t\tassertThat(called.get()).isTrue();\n\t}\n\n\t@Test\n\tvoid arrayIndexedKeyMatchesBaseKey() {\n\t\tAtomicBoolean called = new AtomicBoolean(false);\n\t\tNacosPropertiesKeyListener listener = createListener(called, Set.of(\"storeCodes\"), Set.of());\n\n\t\tlistener.receiveConfigChange(buildEvent(\"storeCodes[3]\"));\n\n\t\tassertThat(called.get()).isTrue();\n\t}\n\n\t@Test\n\tvoid arrayIndexedKeyWithNestedPathMatchesBaseKey() {\n\t\tAtomicBoolean called = new AtomicBoolean(false);\n\t\tNacosPropertiesKeyListener listener = createListener(called, Set.of(\"config.items\"), Set.of());\n\n\t\tlistener.receiveConfigChange(buildEvent(\"config.items[0].name\"));\n\n\t\tassertThat(called.get()).isTrue();\n\t}\n\n\t@Test\n\tvoid unrelatedKeyDoesNotMatch() {\n\t\tAtomicBoolean called = new AtomicBoolean(false);\n\t\tNacosPropertiesKeyListener listener = createListener(called, Set.of(\"myKey\"), Set.of());\n\n\t\tlistener.receiveConfigChange(buildEvent(\"otherKey[0]\"));\n\n\t\tassertThat(called.get()).isFalse();\n\t}\n\n\t@Test\n\tvoid prefixMatchStillWorks() {\n\t\tAtomicBoolean called = new AtomicBoolean(false);\n\t\tNacosPropertiesKeyListener listener = createListener(called, Set.of(), Set.of(\"app.config\"));\n\n\t\tlistener.receiveConfigChange(buildEvent(\"app.config.items[0]\"));\n\n\t\tassertThat(called.get()).isTrue();\n\t}\n\n\t@Test\n\tvoid emptyInterestedKeysPassesAllChanges() {\n\t\tAtomicBoolean called = new AtomicBoolean(false);\n\t\tNacosPropertiesKeyListener listener = createListener(called, Set.of(), Set.of());\n\n\t\tlistener.receiveConfigChange(buildEvent(\"anyKey\"));\n\n\t\tassertThat(called.get()).isTrue();\n\t}\n\n\tprivate NacosPropertiesKeyListener createListener(AtomicBoolean called, Set<String> keys, Set<String> prefixes) {\n\t\tSet<String> interestedKeys = keys.isEmpty() ? null : new HashSet<>(keys);\n\t\tSet<String> interestedPrefixes = prefixes.isEmpty() ? null : new HashSet<>(prefixes);\n\t\treturn new NacosPropertiesKeyListener(new Object(), interestedKeys, interestedPrefixes) {\n\t\t\t@Override\n\t\t\tpublic void configChanged(ConfigChangeEvent event) {\n\t\t\t\tcalled.set(true);\n\t\t\t}\n\t\t};\n\t}\n\n\tprivate ConfigChangeEvent buildEvent(String key) {\n\t\tMap<String, ConfigChangeItem> data = new HashMap<>();\n\t\tConfigChangeItem item = new ConfigChangeItem(key, null, \"newValue\");\n\t\tdata.put(key, item);\n\t\treturn new ConfigChangeEvent(data);\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/test/java/com.alibaba.cloud.nacos/NacosConfigPropertiesTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\n/**\n * NacosConfigProperties Tester.\n */\npublic class NacosConfigPropertiesTest {\n\n\t@Test\n\tvoid testSensitivePropertiesMaskedInToString() {\n\t\tNacosConfigProperties properties = new NacosConfigProperties();\n\t\tproperties.setEndpoint(\"endpoint-test\");\n\t\tproperties.setAccessKey(\"ak-test-123\");\n\t\tproperties.setPassword(\"pwd-test-789\");\n\t\tproperties.setSecretKey(\"sk-test-456\");\n\t\tproperties.setServerAddr(\"127.0.0.1:8848\");\n\t\tString text = properties.toString();\n\n\t\tAssertions.assertThat(text).contains(\"accessKey='******'\");\n\t\tAssertions.assertThat(text).contains(\"secretKey='******'\");\n\t\tAssertions.assertThat(text).doesNotContain(\"ak-test-123\");\n\t\tAssertions.assertThat(text).doesNotContain(\"sk-test-456\");\n\t\tAssertions.assertThat(text).contains(\"endpoint='endpoint-test'\");\n\t\tAssertions.assertThat(text).contains(\"serverAddr='127.0.0.1:8848'\");\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/test/java/com.alibaba.cloud.nacos/configdata/NacosConfigDataLocationResolverTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.configdata;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\nimport com.alibaba.cloud.nacos.NacosConfigProperties;\nimport com.alibaba.cloud.nacos.NacosPropertiesPrefixer;\nimport com.alibaba.nacos.api.config.ConfigService;\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.ArgumentMatchers;\nimport org.mockito.Mockito;\n\nimport org.springframework.boot.bootstrap.ConfigurableBootstrapContext;\nimport org.springframework.boot.context.config.ConfigDataLocation;\nimport org.springframework.boot.context.config.ConfigDataLocationResolverContext;\nimport org.springframework.boot.context.config.Profiles;\nimport org.springframework.boot.context.properties.bind.Binder;\nimport org.springframework.boot.logging.DeferredLogs;\nimport org.springframework.mock.env.MockEnvironment;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * NacosConfigDataLocationResolver Tester.\n *\n * @author freeman\n */\npublic class NacosConfigDataLocationResolverTest {\n\n\tprivate NacosConfigDataLocationResolver resolver;\n\n\tprivate ConfigDataLocationResolverContext context = Mockito.mock(\n\t\t\tConfigDataLocationResolverContext.class);\n\n\tprivate MockEnvironment environment;\n\n\tprivate Binder environmentBinder;\n\n\tprivate ConfigurableBootstrapContext bootstrapContext = Mockito.mock(\n\t\t\tConfigurableBootstrapContext.class);\n\n\t@BeforeEach\n\tvoid setup() {\n\t\tthis.environment = new MockEnvironment();\n\t\tenvironment.setProperty(\"spring.config.import\", \"nacos:test.properties\");\n\t\tthis.environmentBinder = Binder.get(this.environment);\n\t\tthis.resolver = new NacosConfigDataLocationResolver(new DeferredLogs());\n\t\tMockito.when(bootstrapContext.isRegistered(ArgumentMatchers.eq(ConfigService.class))).thenReturn(true);\n\t\tMockito.when(context.getBinder()).thenReturn(environmentBinder);\n\t\tMockito.when(context.getBootstrapContext()).thenReturn(bootstrapContext);\n\t}\n\n\t@Test\n\tvoid testIsResolvable_givenIncorrectPrefix_thenReturnFalse() {\n\t\tassertThat(\n\t\t\t\tthis.resolver.isResolvable(this.context, ConfigDataLocation.of(\"test:\")))\n\t\t\t\t.isFalse();\n\t}\n\n\t@Test\n\tvoid testIsResolvable_givenCorrectPrefix_thenReturnTure() {\n\t\tassertThat(\n\t\t\t\tthis.resolver.isResolvable(this.context, ConfigDataLocation.of(\"nacos:\")))\n\t\t\t\t.isTrue();\n\t\tassertThat(this.resolver.isResolvable(this.context,\n\t\t\t\tConfigDataLocation.of(\"optional:nacos:\"))).isTrue();\n\t}\n\n\t@Test\n\tvoid testIsResolvable_givenDisable_thenReturnFalse() {\n\n\t\tString prefix = NacosPropertiesPrefixer.getPrefix(environment);\n\n\t\tthis.environment.setProperty(prefix + \".config.enabled\", \"false\");\n\t\tassertThat(\n\t\t\t\tthis.resolver.isResolvable(this.context, ConfigDataLocation.of(\"nacos:\")))\n\t\t\t\t.isFalse();\n\t}\n\n\t@Test\n\tvoid testResolveProfileSpecific_givenNothing_thenReturnDefaultProfile() {\n\t\tNacosConfigDataResource resource = testResolveProfileSpecific();\n\t\tassertThat(resource.getProfiles()).isEqualTo(\"default\");\n\t}\n\n\t@Test\n\tvoid testStartWithASlashIsOK() {\n\t\tString locationUri = \"nacos:/app\";\n\t\tList<NacosConfigDataResource> resources = testUri(locationUri);\n\t\tAssertions.assertThat(resources).hasSize(1);\n\t\tassertThat(resources.get(0).getConfig().getDataId()).isEqualTo(\"app\");\n\n\t\tlocationUri = \"nacos:app\";\n\t\tresources = testUri(locationUri);\n\t\tAssertions.assertThat(resources).hasSize(1);\n\t\tassertThat(resources.get(0).getConfig().getDataId()).isEqualTo(\"app\");\n\t}\n\n\t@Test\n\tvoid testDataIdMustBeSpecified() {\n\t\tString locationUri = \"nacos:\";\n\t\tAssertions.assertThatThrownBy(() -> testUri(locationUri))\n\t\t\t\t.hasMessage(\"dataId must be specified\");\n\t}\n\n\t@Test\n\tvoid testInvalidDataId() {\n\t\tString locationUri = \"nacos:test/test.yml\";\n\t\tAssertions.assertThatThrownBy(() -> testUri(locationUri)).hasMessage(\"illegal dataId\");\n\t}\n\n\t@Test\n\tvoid whenCustomizeSuffix_thenOverrideDefault() {\n\t\tString locationUri = \"nacos:app\";\n\t\tList<NacosConfigDataResource> resources = testUri(locationUri);\n\t\tAssertions.assertThat(resources).hasSize(1);\n\t\tassertThat(resources.get(0).getConfig().getDataId()).isEqualTo(\"app\");\n\t\tassertThat(resources.get(0).getConfig().getSuffix()).isEqualTo(\"properties\");\n\n\t\tenvironment.setProperty(\"spring.nacos.config.file-extension\", \"yml\");\n\t\tlocationUri = \"nacos:app\";\n\t\tresources = testUri(locationUri);\n\t\tAssertions.assertThat(resources).hasSize(1);\n\t\tassertThat(resources.get(0).getConfig().getDataId()).isEqualTo(\"app\");\n\t\tassertThat(resources.get(0).getConfig().getSuffix()).isEqualTo(\"yml\");\n\n\t\tlocationUri = \"nacos:app.json\";\n\t\tresources = testUri(locationUri);\n\t\tAssertions.assertThat(resources).hasSize(1);\n\t\tassertThat(resources.get(0).getConfig().getDataId()).isEqualTo(\"app.json\");\n\t\tassertThat(resources.get(0).getConfig().getSuffix()).isEqualTo(\"json\");\n\t}\n\n\t@Test\n\tvoid testUrisInLocationShouldOverridesProperty() {\n\t\tenvironment.setProperty(\"spring.nacos.config.group\", \"default\");\n\t\tenvironment.setProperty(\"spring.nacos.config.refreshEnabled\", \"true\");\n\t\tString locationUri = \"nacos:test.yml?group=not_default&refreshEnabled=false\";\n\t\tList<NacosConfigDataResource> resources = testUri(locationUri);\n\t\tAssertions.assertThat(resources).hasSize(1);\n\t\tNacosConfigDataResource resource = resources.get(0);\n\t\tassertThat(resource.getConfig().getGroup()).isEqualTo(\"not_default\");\n\t\tassertThat(resource.getConfig().getSuffix()).isEqualTo(\"yml\");\n\t\tassertThat(resource.getConfig().isRefreshEnabled()).isFalse();\n\t\tassertThat(resource.getConfig().getDataId()).isEqualTo(\"test.yml\");\n\t}\n\n\t@Test\n\tvoid testSetCommonPropertiesIsOK() {\n\t\tenvironment.setProperty(\"spring.nacos.username\", \"root\");\n\t\tenvironment.setProperty(\"spring.nacos.password\", \"root\");\n\t\tenvironment.setProperty(\"spring.nacos.server-addr\", \"127.0.0.1:8888\");\n\t\tString locationUri = \"nacos:test.yml\";\n\t\tList<NacosConfigDataResource> resources = testUri(locationUri);\n\n\t\tAssertions.assertThat(resources).hasSize(1);\n\t\tNacosConfigDataResource resource = resources.get(0);\n\t\tassertThat(resource.getProperties().getUsername()).isEqualTo(\"root\");\n\t\tassertThat(resource.getProperties().getPassword()).isEqualTo(\"root\");\n\t\tassertThat(resource.getProperties().getServerAddr()).isEqualTo(\"127.0.0.1:8888\");\n\t}\n\n\t@Test\n\tvoid testCommonPropertiesHasLowerPriority() {\n\t\tenvironment.setProperty(\"spring.nacos.username\", \"root\");\n\t\tenvironment.setProperty(\"spring.nacos.password\", \"root\");\n\t\tenvironment.setProperty(\"spring.nacos.config.password\", \"not_root\");\n\t\tenvironment.setProperty(\"spring.nacos.server-addr\", \"127.0.0.1:8888\");\n\t\tenvironment.setProperty(\"spring.nacos.config.server-addr\",\n\t\t\t\t\"127.0.0.1:9999\");\n\t\tString locationUri = \"nacos:test.yml\";\n\t\tList<NacosConfigDataResource> resources = testUri(locationUri);\n\n\t\tAssertions.assertThat(resources).hasSize(1);\n\t\tNacosConfigDataResource resource = resources.get(0);\n\t\tassertThat(resource.getProperties().getUsername()).isEqualTo(\"root\");\n\t\tassertThat(resource.getProperties().getPassword()).isEqualTo(\"not_root\");\n\t\tassertThat(resource.getProperties().getServerAddr()).isEqualTo(\"127.0.0.1:9999\");\n\t}\n\n\tprivate List<NacosConfigDataResource> testUri(String locationUri,\n\t\t\tString... activeProfiles) {\n\t\tProfiles profiles = Mockito.mock(Profiles.class);\n\t\tMockito.when(profiles.getActive()).thenReturn(Arrays.asList(activeProfiles));\n\t\treturn this.resolver.resolveProfileSpecific(context,\n\t\t\t\tConfigDataLocation.of(locationUri), profiles);\n\t}\n\n\t@Test\n\tvoid whenNoneInBootstrapContext_thenCreateNewConfigClientProperties() {\n\t\tMockito.when(bootstrapContext.isRegistered(ArgumentMatchers.eq(NacosConfigProperties.class)))\n\t\t\t\t.thenReturn(false);\n\t\tMockito.when(bootstrapContext.get(ArgumentMatchers.eq(NacosConfigProperties.class)))\n\t\t\t\t.thenReturn(new NacosConfigProperties());\n\t\tList<NacosConfigDataResource> resources = this.resolver.resolveProfileSpecific(\n\t\t\t\tcontext, ConfigDataLocation.of(\"nacos:test.yml\"), Mockito.mock(Profiles.class));\n\t\tAssertions.assertThat(resources).hasSize(1);\n\t\tMockito.verify(bootstrapContext, Mockito.times(0)).get(ArgumentMatchers.eq(NacosConfigProperties.class));\n\t\tNacosConfigDataResource resource = resources.get(0);\n\t\tassertThat(resource.getConfig().getGroup()).isEqualTo(\"DEFAULT_GROUP\");\n\t\tassertThat(resource.getConfig().getDataId()).isEqualTo(\"test.yml\");\n\t}\n\n\tprivate NacosConfigDataResource testResolveProfileSpecific() {\n\t\treturn testResolveProfileSpecific(\"default\");\n\t}\n\n\tprivate NacosConfigDataResource testResolveProfileSpecific(String activeProfile) {\n\t\tProfiles profiles = Mockito.mock(Profiles.class);\n\t\tif (activeProfile != null) {\n\t\t\tMockito.when(profiles.getActive())\n\t\t\t\t\t.thenReturn(Collections.singletonList(activeProfile));\n\t\t\tMockito.when(profiles.getAccepted())\n\t\t\t\t\t.thenReturn(Collections.singletonList(activeProfile));\n\t\t}\n\n\t\tList<NacosConfigDataResource> resources = this.resolver.resolveProfileSpecific(\n\t\t\t\tcontext, ConfigDataLocation.of(\"nacos:test.yml\"), profiles);\n\t\tAssertions.assertThat(resources).hasSize(1);\n\t\treturn resources.get(0);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-alibaba-nacos-config/src/test/java/com.alibaba.cloud.nacos/endpoint/NacosConfigEndpointTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.endpoint;\n\nimport java.util.Map;\n\nimport com.alibaba.cloud.nacos.NacosConfigAutoConfiguration;\nimport com.alibaba.cloud.nacos.NacosConfigManager;\nimport com.alibaba.cloud.nacos.NacosConfigProperties;\nimport com.alibaba.cloud.nacos.refresh.NacosRefreshHistory;\nimport com.alibaba.nacos.client.config.NacosConfigService;\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.health.contributor.Health;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n *\n * @author xiaojing\n * @author freeman\n */\n@SpringBootTest(classes = NacosConfigEndpointTests.TestConfig.class, webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = {\n\t\t\"spring.application.name=test-name\",\n\t\t\"spring.nacos.config.server-addr=127.0.0.1:8848\",\n\t\t\"spring.nacos.config.file-extension=properties\",\n\t\t\"spring.config.import[0]=nacos:test-name.properties?refreshEnabled=true\"})\npublic class NacosConfigEndpointTests {\n\n\t@Autowired\n\tprivate NacosConfigProperties properties;\n\n\t@Autowired\n\tprivate NacosRefreshHistory refreshHistory;\n\n\tstatic {\n\n\t\ttry {\n\t\t\tNacosConfigService mockedNacosConfigService = Mockito\n\t\t\t\t\t.mock(NacosConfigService.class);\n\t\t\tMockito.when(mockedNacosConfigService.getServerStatus()).thenReturn(\"UP\");\n\t\t\tReflectionTestUtils.setField(NacosConfigManager.class, \"service\",\n\t\t\t\t\tmockedNacosConfigService);\n\t\t}\n\t\tcatch (Exception ignore) {\n\t\t\tignore.printStackTrace();\n\t\t}\n\t}\n\t@Test\n\tpublic void contextLoads() throws Exception {\n\n\t\tcheckoutEndpoint();\n\t\tcheckoutAcmHealthIndicator();\n\n\t}\n\n\tprivate void checkoutAcmHealthIndicator() {\n\t\ttry {\n\t\t\tHealth.Builder builder = new Health.Builder();\n\n\t\t\tNacosConfigHealthIndicator healthIndicator = new NacosConfigHealthIndicator(\n\t\t\t\t\tproperties.configServiceInstance());\n\t\t\thealthIndicator.doHealthCheck(builder);\n\n\t\t\tHealth.Builder builder1 = new Health.Builder();\n\t\t\tbuilder1.up();\n\n\t\t\tAssertions.assertThat(builder.build()).isEqualTo(builder1.build());\n\t\t}\n\t\tcatch (Exception ignore) {\n\n\t\t}\n\n\t}\n\n\tprivate void checkoutEndpoint() throws Exception {\n\t\tNacosConfigEndpoint endpoint = new NacosConfigEndpoint(properties,\n\t\t\t\trefreshHistory);\n\t\tMap<String, Object> map = endpoint.invoke();\n\n\t\tassertThat(properties).isEqualTo(map.get(\"NacosConfigProperties\"));\n\t\tassertThat(refreshHistory.getRecords()).isEqualTo(map.get(\"RefreshHistory\"));\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@ImportAutoConfiguration({ NacosConfigEndpointAutoConfiguration.class,\n\t\t\tNacosConfigAutoConfiguration.class})\n\tpublic static class TestConfig {\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-starters</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>spring-cloud-alibaba-commons</artifactId>\n    <name>Spring Cloud Alibaba Commons</name>\n\n    <dependencies>\n\n        <!-- Spring -->\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-context</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n    </dependencies>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/context/support/PropertySourcesUtils.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.commons.context.support;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\nimport org.springframework.core.env.ConfigurableEnvironment;\nimport org.springframework.core.env.EnumerablePropertySource;\nimport org.springframework.core.env.MutablePropertySources;\nimport org.springframework.core.env.PropertyResolver;\nimport org.springframework.core.env.PropertySource;\nimport org.springframework.core.env.PropertySources;\nimport org.springframework.core.env.PropertySourcesPropertyResolver;\n\nimport static java.util.Collections.unmodifiableMap;\n\n/**\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n * @author <a href=\"mailto:yuluo08290126@gmail.com\">yuluo</a>\n * {@link PropertySources} Utilities\n * {@see PropertySources}\n */\npublic final class PropertySourcesUtils {\n\n\tprivate PropertySourcesUtils() {\n\t}\n\n\t/**\n\t * Empty String array.\n\t */\n\tpublic static final String[] EMPTY_STRING_ARRAY = {};\n\n\t/**\n\t * Get Sub {@link Properties}.\n\t *\n\t * @param propertySources {@link PropertySource} Iterable.\n\t * @param prefix          the prefix of property name.\n\t * @return Map\n\t * @see Properties\n\t */\n\tpublic static Map<String, Object> getSubProperties(Iterable<PropertySource<?>> propertySources, String prefix) {\n\n\t\tMutablePropertySources mutablePropertySources = new MutablePropertySources();\n\n\t\tfor (PropertySource<?> source : propertySources) {\n\t\t\tmutablePropertySources.addLast(source);\n\t\t}\n\n\t\treturn getSubProperties(mutablePropertySources, prefix);\n\n\t}\n\n\t/**\n\t * Get Sub {@link Properties}.\n\t *\n\t * @param environment {@link ConfigurableEnvironment}.\n\t * @param prefix      the prefix of property name.\n\t * @return Map\n\t * @see Properties\n\t */\n\tpublic static Map<String, Object> getSubProperties(ConfigurableEnvironment environment, String prefix) {\n\n\t\treturn getSubProperties(environment.getPropertySources(), environment, prefix);\n\t}\n\n\t/**\n\t * Normalize the prefix.\n\t *\n\t * @param prefix the prefix.\n\t * @return the prefix.\n\t */\n\tpublic static String normalizePrefix(String prefix) {\n\t\treturn prefix.endsWith(\".\") ? prefix : prefix + \".\";\n\t}\n\n\t/**\n\t * Get prefixed {@link Properties}.\n\t *\n\t * @param propertySources {@link PropertySources}.\n\t * @param prefix          the prefix of property name.\n\t * @return Map\n\t * @see Properties\n\t */\n\tpublic static Map<String, Object> getSubProperties(PropertySources propertySources, String prefix) {\n\n\t\treturn getSubProperties(propertySources, new PropertySourcesPropertyResolver(propertySources), prefix);\n\t}\n\n\t/**\n\t * Get prefixed {@link Properties}.\n\t *\n\t * @param propertySources  {@link PropertySources}.\n\t * @param propertyResolver {@link PropertyResolver} to resolve the placeholder if present.\n\t * @param prefix           the prefix of property name.\n\t * @return Map\n\t * @see Properties\n\t */\n\tpublic static Map<String, Object> getSubProperties(PropertySources propertySources, PropertyResolver propertyResolver, String prefix) {\n\n\t\tMap<String, Object> subProperties = new LinkedHashMap<String, Object>();\n\n\t\tString normalizedPrefix = normalizePrefix(prefix);\n\n\t\tfor (PropertySource<?> source : propertySources) {\n\t\t\tfor (String name : getPropertyNames(source)) {\n\t\t\t\tif (!subProperties.containsKey(name) && name.startsWith(normalizedPrefix)) {\n\t\t\t\t\tString subName = name.substring(normalizedPrefix.length());\n\t\t\t\t\tif (!subProperties.containsKey(subName)) { // take first one\n\t\t\t\t\t\tObject value = source.getProperty(name);\n\t\t\t\t\t\tif (value instanceof String) {\n\t\t\t\t\t\t\t// Resolve placeholder\n\t\t\t\t\t\t\tvalue = propertyResolver.resolvePlaceholders((String) value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsubProperties.put(subName, value);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn unmodifiableMap(subProperties);\n\t}\n\n\t/**\n\t * Get the property names as the array from the specified {@link PropertySource} instance.\n\t *\n\t * @param propertySource {@link PropertySource} instance.\n\t * @return non-null\n\t */\n\tpublic static String[] getPropertyNames(PropertySource propertySource) {\n\n\t\tString[] propertyNames = propertySource instanceof EnumerablePropertySource ?\n\t\t\t\t((EnumerablePropertySource<?>) propertySource).getPropertyNames() : null;\n\n\t\tif (propertyNames == null) {\n\t\t\tpropertyNames = EMPTY_STRING_ARRAY;\n\t\t}\n\n\t\treturn propertyNames;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/Charsets.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.commons.io;\n\nimport java.nio.charset.Charset;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Collections;\nimport java.util.SortedMap;\nimport java.util.TreeMap;\n\n/**\n * The Charsets constants, copy from apache commons-io.\n *\n * @author <a href=\"mailto:chenxilzx1@gmail.com\">theonefx</a>\n */\npublic final class Charsets {\n\n\tprivate Charsets() {\n\t}\n\n\t/**\n\t * Constructs a sorted map from canonical charset names to charset objects required of\n\t * every implementation of the Java platform.\n\t * <p>\n\t * From the Java documentation\n\t * <a href=\"https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html\">\n\t * Standard charsets</a>:\n\t * </p>\n\t *\n\t * @return An immutable, case-insensitive map from canonical charset names to charset\n\t * objects.\n\t * @see Charset#availableCharsets()\n\t */\n\tpublic static SortedMap<String, Charset> requiredCharsets() {\n\t\t// maybe cache?\n\t\tfinal TreeMap<String, Charset> m = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);\n\t\tm.put(StandardCharsets.ISO_8859_1.name(), StandardCharsets.ISO_8859_1);\n\t\tm.put(StandardCharsets.US_ASCII.name(), StandardCharsets.US_ASCII);\n\t\tm.put(StandardCharsets.UTF_16.name(), StandardCharsets.UTF_16);\n\t\tm.put(StandardCharsets.UTF_16BE.name(), StandardCharsets.UTF_16BE);\n\t\tm.put(StandardCharsets.UTF_16LE.name(), StandardCharsets.UTF_16LE);\n\t\tm.put(StandardCharsets.UTF_8.name(), StandardCharsets.UTF_8);\n\t\treturn Collections.unmodifiableSortedMap(m);\n\t}\n\n\t/**\n\t * Returns the given Charset or the default Charset if the given Charset is null.\n\t *\n\t * @param charset A charset or null.\n\t * @return the given Charset or the default Charset if the given Charset is null\n\t */\n\tpublic static Charset toCharset(final Charset charset) {\n\t\treturn charset == null ? Charset.defaultCharset() : charset;\n\t}\n\n\t/**\n\t * Returns a Charset for the named charset. If the name is null, return the default\n\t * Charset.\n\t *\n\t * @param charset The name of the requested charset, may be null.\n\t * @return a Charset for the named charset\n\t * @throws java.nio.charset.UnsupportedCharsetException If the named charset is unavailable\n\t */\n\tpublic static Charset toCharset(final String charset) {\n\t\treturn charset == null ? Charset.defaultCharset() : Charset.forName(charset);\n\t}\n\n\t/**\n\t * CharEncodingISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.\n\t * <p>\n\t * Every implementation of the Java platform is required to support this character\n\t * encoding.\n\t * </p>\n\t *\n\t * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}\n\t * @see <a href=\n\t * \"https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html\">Standard\n\t * charsets</a>\n\t */\n\t@Deprecated\n\tpublic static final Charset ISO_8859_1 = StandardCharsets.ISO_8859_1;\n\n\t/**\n\t * <p>\n\t * Seven-bit ASCII, also known as ISO646-US, also known as the Basic Latin block of\n\t * the Unicode character set.\n\t * </p>\n\t * <p>\n\t * Every implementation of the Java platform is required to support this character\n\t * encoding.\n\t * </p>\n\t *\n\t * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}\n\t * @see <a href=\n\t * \"https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html\">Standard\n\t * charsets</a>\n\t */\n\t@Deprecated\n\tpublic static final Charset US_ASCII = StandardCharsets.US_ASCII;\n\n\t/**\n\t * <p>\n\t * Sixteen-bit Unicode Transformation Format, The byte order specified by a mandatory\n\t * initial byte-order mark (either order accepted on input, big-endian used on output)\n\t * </p>\n\t * <p>\n\t * Every implementation of the Java platform is required to support this character\n\t * encoding.\n\t * </p>\n\t *\n\t * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}\n\t * @see <a href=\n\t * \"https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html\">Standard\n\t * charsets</a>\n\t */\n\t@Deprecated\n\tpublic static final Charset UTF_16 = StandardCharsets.UTF_16;\n\n\t/**\n\t * <p>\n\t * Sixteen-bit Unicode Transformation Format, big-endian byte order.\n\t * </p>\n\t * <p>\n\t * Every implementation of the Java platform is required to support this character\n\t * encoding.\n\t * </p>\n\t *\n\t * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}\n\t * @see <a href=\n\t * \"https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html\">Standard\n\t * charsets</a>\n\t */\n\t@Deprecated\n\tpublic static final Charset UTF_16BE = StandardCharsets.UTF_16BE;\n\n\t/**\n\t * <p>\n\t * Sixteen-bit Unicode Transformation Format, little-endian byte order.\n\t * </p>\n\t * <p>\n\t * Every implementation of the Java platform is required to support this character\n\t * encoding.\n\t * </p>\n\t *\n\t * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}\n\t * @see <a href=\n\t * \"https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html\">Standard\n\t * charsets</a>\n\t */\n\t@Deprecated\n\tpublic static final Charset UTF_16LE = StandardCharsets.UTF_16LE;\n\n\t/**\n\t * <p>\n\t * Eight-bit Unicode Transformation Format.\n\t * </p>\n\t * <p>\n\t * Every implementation of the Java platform is required to support this character\n\t * encoding.\n\t * </p>\n\t *\n\t * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}\n\t * @see <a href=\n\t * \"https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html\">Standard\n\t * charsets</a>\n\t */\n\t@Deprecated\n\tpublic static final Charset UTF_8 = StandardCharsets.UTF_8;\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/FileUtils.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.commons.io;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.nio.charset.Charset;\n\n/**\n * FileUtils. copy from apache commons-io.\n *\n * @author <a href=\"mailto:chenxilzx1@gmail.com\">theonefx</a>\n */\npublic final class FileUtils {\n\n\tprivate FileUtils() {\n\t}\n\n\t// -----------------------------------------------------------------------\n\t/**\n\t * Opens a {@link java.io.FileInputStream} for the specified file, providing better\n\t * error messages than simply calling <code>new FileInputStream(file)</code>.\n\t * <p>\n\t * At the end of the method either the stream will be successfully opened, or an\n\t * exception will have been thrown.\n\t * <p>\n\t * An exception is thrown if the file does not exist. An exception is thrown if the\n\t * file object exists but is a directory. An exception is thrown if the file exists\n\t * but cannot be read.\n\t * @param file the file to open for input, must not be {@code null}\n\t * @return a new {@link java.io.FileInputStream} for the specified file\n\t * @throws java.io.FileNotFoundException if the file does not exist\n\t * @throws IOException if the file object is a directory\n\t * @throws IOException if the file cannot be read\n\t * @since 1.3\n\t */\n\tpublic static FileInputStream openInputStream(final File file) throws IOException {\n\t\tif (file.exists()) {\n\t\t\tif (file.isDirectory()) {\n\t\t\t\tthrow new IOException(\"File '\" + file + \"' exists but is a directory\");\n\t\t\t}\n\t\t\tif (!file.canRead()) {\n\t\t\t\tthrow new IOException(\"File '\" + file + \"' cannot be read\");\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tthrow new FileNotFoundException(\"File '\" + file + \"' does not exist\");\n\t\t}\n\t\treturn new FileInputStream(file);\n\t}\n\n\t// -----------------------------------------------------------------------\n\t/**\n\t * Reads the contents of a file into a String. The file is always closed.\n\t * @param file the file to read, must not be {@code null}\n\t * @param encoding the encoding to use, {@code null} means platform default\n\t * @return the file contents, never {@code null}\n\t * @throws IOException in case of an I/O error\n\t */\n\tpublic static String readFileToString(final File file, final Charset encoding)\n\t\t\tthrows IOException {\n\t\ttry (InputStream in = openInputStream(file)) {\n\t\t\treturn IOUtils.toString(in, Charsets.toCharset(encoding));\n\t\t}\n\t}\n\n\t/**\n\t * Reads the contents of a file into a String. The file is always closed.\n\t * @param file the file to read, must not be {@code null}\n\t * @param encoding the encoding to use, {@code null} means platform default\n\t * @return the file contents, never {@code null}\n\t * @throws java.io.IOException in case of an I/O error\n\t * @throws java.nio.charset.UnsupportedCharsetException thrown instead of\n\t * {@link java.io .UnsupportedEncodingException} in version 2.2 if the encoding is not\n\t * supported.\n\t */\n\tpublic static String readFileToString(final File file, final String encoding)\n\t\t\tthrows IOException {\n\t\treturn readFileToString(file, Charsets.toCharset(encoding));\n\t}\n\n\t/**\n\t * Reads the contents of a file into a String using the default encoding for the VM.\n\t * The file is always closed.\n\t * @param file the file to read, must not be {@code null}\n\t * @return the file contents, never {@code null}\n\t * @throws IOException in case of an I/O error\n\t * @deprecated 2.5 use {@link #readFileToString(File, String)} instead (and specify\n\t * the appropriate encoding)\n\t */\n\t@Deprecated\n\tpublic static String readFileToString(final File file) throws IOException {\n\t\treturn readFileToString(file, Charset.defaultCharset());\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/IOUtils.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.commons.io;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.OutputStream;\nimport java.io.Reader;\nimport java.io.Writer;\nimport java.nio.charset.Charset;\n\n/**\n * The IOUtils. copy from apache commons-io.\n *\n * @author <a href=\"mailto:chenxilzx1@gmail.com\">theonefx</a>\n */\npublic final class IOUtils {\n\n\t/**\n\t * Represents the end-of-file (or stream).\n\t * @since 2.5 (made public)\n\t */\n\tpublic static final int EOF = -1;\n\n\t/**\n\t * The default buffer size ({@value}) to use for.\n\t * {@link #copyLarge(InputStream, java.io.OutputStream)} and\n\t * {@link #copyLarge(Reader, Writer)}\n\t */\n\tprivate static final int DEFAULT_BUFFER_SIZE = 1024 * 4;\n\n\tprivate IOUtils() {\n\n\t}\n\n\t/**\n\t * Gets the contents of an <code>InputStream</code> as a String using the specified\n\t * character encoding.\n\t * <p>\n\t * This method buffers the input internally, so there is no need to use a\n\t * <code>BufferedInputStream</code>.\n\t * </p>\n\t * @param input the <code>InputStream</code> to read from\n\t * @param encoding the encoding to use, null means platform default\n\t * @return the requested String\n\t * @throws NullPointerException if the input is null\n\t * @throws java.io.IOException if an I/O error occurs\n\t * @since 2.3\n\t */\n\tpublic static String toString(final InputStream input, final Charset encoding)\n\t\t\tthrows IOException {\n\t\ttry (StringBuilderWriter sw = new StringBuilderWriter()) {\n\t\t\tcopy(input, sw, encoding);\n\t\t\treturn sw.toString();\n\t\t}\n\t}\n\n\t// copy from Reader\n\t// -----------------------------------------------------------------------\n\n\t/**\n\t * Copies chars from a <code>Reader</code> to a <code>Writer</code>.\n\t * <p>\n\t * This method buffers the input internally, so there is no need to use a\n\t * <code>BufferedReader</code>.\n\t * <p>\n\t * Large streams (over 2GB) will return a chars copied value of <code>-1</code> after\n\t * the copy has completed since the correct number of chars cannot be returned as an\n\t * int. For large streams use the <code>copyLarge(Reader, Writer)</code> method.\n\t * @param input the <code>Reader</code> to read from\n\t * @param output the <code>Writer</code> to write to\n\t * @return the number of characters copied, or -1 if &gt; Integer.MAX_VALUE\n\t * @throws NullPointerException if the input or output is null\n\t * @throws IOException if an I/O error occurs\n\t * @since 1.1\n\t */\n\tpublic static int copy(final Reader input, final Writer output) throws IOException {\n\t\tfinal long count = copyLarge(input, output);\n\t\tif (count > Integer.MAX_VALUE) {\n\t\t\treturn -1;\n\t\t}\n\t\treturn (int) count;\n\t}\n\n\t/**\n\t * Copies bytes from an <code>InputStream</code> to chars on a <code>Writer</code>\n\t * using the specified character encoding.\n\t * <p>\n\t * This method buffers the input internally, so there is no need to use a\n\t * <code>BufferedInputStream</code>.\n\t * <p>\n\t * This method uses {@link java.io.InputStreamReader}.\n\t * @param input the <code>InputStream</code> to read from\n\t * @param output the <code>Writer</code> to write to\n\t * @param inputEncoding the encoding to use for the input stream, null means platform\n\t * default\n\t * @throws NullPointerException if the input or output is null\n\t * @throws IOException if an I/O error occurs\n\t * @since 2.3\n\t */\n\tpublic static void copy(final InputStream input, final Writer output,\n\t\t\tfinal Charset inputEncoding) throws IOException {\n\t\tfinal InputStreamReader in = new InputStreamReader(input,\n\t\t\t\tCharsets.toCharset(inputEncoding));\n\t\tcopy(in, output);\n\t}\n\n\t/**\n\t * Copies bytes from an <code>InputStream</code> to an <code>OutputStream</code> using\n\t * an internal buffer of the given size.\n\t * <p>\n\t * This method buffers the input internally, so there is no need to use a\n\t * <code>BufferedInputStream</code>.\n\t * <p>\n\t * @param input the <code>InputStream</code> to read from\n\t * @param output the <code>OutputStream</code> to write to\n\t * @param bufferSize the bufferSize used to copy from the input to the output\n\t * @return the number of bytes copied\n\t * @throws NullPointerException if the input or output is null\n\t * @throws IOException if an I/O error occurs\n\t * @since 2.5\n\t */\n\tpublic static long copy(final InputStream input, final OutputStream output,\n\t\t\tfinal int bufferSize) throws IOException {\n\t\treturn copyLarge(input, output, new byte[bufferSize]);\n\t}\n\n\t/**\n\t * Copies chars from a large (over 2GB) <code>Reader</code> to a <code>Writer</code>.\n\t * <p>\n\t * This method buffers the input internally, so there is no need to use a\n\t * <code>BufferedReader</code>.\n\t * <p>\n\t * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.\n\t * @param input the <code>Reader</code> to read from\n\t * @param output the <code>Writer</code> to write to\n\t * @return the number of characters copied\n\t * @throws NullPointerException if the input or output is null\n\t * @throws IOException if an I/O error occurs\n\t * @since 1.3\n\t */\n\tpublic static long copyLarge(final Reader input, final Writer output)\n\t\t\tthrows IOException {\n\t\treturn copyLarge(input, output, new char[DEFAULT_BUFFER_SIZE]);\n\t}\n\n\t/**\n\t * Copies chars from a large (over 2GB) <code>Reader</code> to a <code>Writer</code>.\n\t * <p>\n\t * This method uses the provided buffer, so there is no need to use a\n\t * <code>BufferedReader</code>.\n\t * <p>\n\t * @param input the <code>Reader</code> to read from\n\t * @param output the <code>Writer</code> to write to\n\t * @param buffer the buffer to be used for the copy\n\t * @return the number of characters copied\n\t * @throws NullPointerException if the input or output is null\n\t * @throws IOException if an I/O error occurs\n\t * @since 2.2\n\t */\n\tpublic static long copyLarge(final Reader input, final Writer output,\n\t\t\tfinal char[] buffer) throws IOException {\n\t\tlong count = 0;\n\t\tint n;\n\t\twhile (EOF != (n = input.read(buffer))) {\n\t\t\toutput.write(buffer, 0, n);\n\t\t\tcount += n;\n\t\t}\n\t\treturn count;\n\t}\n\n\t/**\n\t * Copies bytes from a large (over 2GB) <code>InputStream</code> to an\n\t * <code>OutputStream</code>.\n\t * <p>\n\t * This method buffers the input internally, so there is no need to use a\n\t * <code>BufferedInputStream</code>.\n\t * <p>\n\t * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.\n\t * @param input the <code>InputStream</code> to read from\n\t * @param output the <code>OutputStream</code> to write to\n\t * @return the number of bytes copied\n\t * @throws NullPointerException if the input or output is null\n\t * @throws IOException if an I/O error occurs\n\t * @since 1.3\n\t */\n\tpublic static long copyLarge(final InputStream input, final OutputStream output)\n\t\t\tthrows IOException {\n\t\treturn copy(input, output, DEFAULT_BUFFER_SIZE);\n\t}\n\n\t/**\n\t * Copies bytes from a large (over 2GB) <code>InputStream</code> to an\n\t * <code>OutputStream</code>.\n\t * <p>\n\t * This method uses the provided buffer, so there is no need to use a\n\t * <code>BufferedInputStream</code>.\n\t * <p>\n\t * @param input the <code>InputStream</code> to read from\n\t * @param output the <code>OutputStream</code> to write to\n\t * @param buffer the buffer to use for the copy\n\t * @return the number of bytes copied\n\t * @throws NullPointerException if the input or output is null\n\t * @throws IOException if an I/O error occurs\n\t * @since 2.2\n\t */\n\tpublic static long copyLarge(final InputStream input, final OutputStream output,\n\t\t\tfinal byte[] buffer) throws IOException {\n\t\tlong count = 0;\n\t\tint n;\n\t\twhile (EOF != (n = input.read(buffer))) {\n\t\t\toutput.write(buffer, 0, n);\n\t\t\tcount += n;\n\t\t}\n\t\treturn count;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/StringBuilderWriter.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.commons.io;\n\nimport java.io.Serializable;\nimport java.io.Writer;\n\n/**\n * Copy from apache commons-io.\n *\n * @author <a href=\"mailto:chenxilzx1@gmail.com\">theonefx</a>\n */\npublic class StringBuilderWriter extends Writer implements Serializable {\n\n\tprivate static final long serialVersionUID = -146927496096066153L;\n\n\tprivate final StringBuilder builder;\n\n\t/**\n\t * Constructs a new {@link StringBuilder} instance with default capacity.\n\t */\n\tpublic StringBuilderWriter() {\n\t\tthis.builder = new StringBuilder();\n\t}\n\n\t/**\n\t * Constructs a new {@link StringBuilder} instance with the specified capacity.\n\t * @param capacity The initial capacity of the underlying {@link StringBuilder}\n\t */\n\tpublic StringBuilderWriter(final int capacity) {\n\t\tthis.builder = new StringBuilder(capacity);\n\t}\n\n\t/**\n\t * Constructs a new instance with the specified {@link StringBuilder}.\n\t *\n\t * <p>\n\t * If {@code builder} is null a new instance with default capacity will be created.\n\t * </p>\n\t * @param builder The String builder. May be null.\n\t */\n\tpublic StringBuilderWriter(final StringBuilder builder) {\n\t\tthis.builder = builder != null ? builder : new StringBuilder();\n\t}\n\n\t/**\n\t * Appends a single character to this Writer.\n\t * @param value The character to append\n\t * @return This writer instance\n\t */\n\t@Override\n\tpublic Writer append(final char value) {\n\t\tbuilder.append(value);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Appends a character sequence to this Writer.\n\t * @param value The character to append\n\t * @return This writer instance\n\t */\n\t@Override\n\tpublic Writer append(final CharSequence value) {\n\t\tbuilder.append(value);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Appends a portion of a character sequence to the {@link StringBuilder}.\n\t * @param value The character to append\n\t * @param start The index of the first character\n\t * @param end The index of the last character + 1\n\t * @return This writer instance\n\t */\n\t@Override\n\tpublic Writer append(final CharSequence value, final int start, final int end) {\n\t\tbuilder.append(value, start, end);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Closing this writer has no effect.\n\t */\n\t@Override\n\tpublic void close() {\n\t\t// no-op\n\t}\n\n\t/**\n\t * Flushing this writer has no effect.\n\t */\n\t@Override\n\tpublic void flush() {\n\t\t// no-op\n\t}\n\n\t/**\n\t * Writes a String to the {@link StringBuilder}.\n\t * @param value The value to write\n\t */\n\t@Override\n\tpublic void write(final String value) {\n\t\tif (value != null) {\n\t\t\tbuilder.append(value);\n\t\t}\n\t}\n\n\t/**\n\t * Writes a portion of a character array to the {@link StringBuilder}.\n\t * @param value The value to write\n\t * @param offset The index of the first character\n\t * @param length The number of characters to write\n\t */\n\t@Override\n\tpublic void write(final char[] value, final int offset, final int length) {\n\t\tif (value != null) {\n\t\t\tbuilder.append(value, offset, length);\n\t\t}\n\t}\n\n\t/**\n\t * Returns the underlying builder.\n\t * @return The underlying builder\n\t */\n\tpublic StringBuilder getBuilder() {\n\t\treturn builder;\n\t}\n\n\t/**\n\t * Returns {@link StringBuilder#toString()}.\n\t * @return The contents of the String builder.\n\t */\n\t@Override\n\tpublic String toString() {\n\t\treturn builder.toString();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/lang/StringUtils.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.commons.lang;\n\n/**\n * StringUtils. copy from apache common-lang3.\n *\n * @author <a href=\"mailto:chenxilzx1@gmail.com\">theonefx</a>\n */\npublic final class StringUtils {\n\n\t/**\n\t * The empty String {@code \"\"}.\n\t *\n\t * @since 2.0\n\t */\n\tpublic static final String EMPTY = \"\";\n\n\t/**\n\t * Represents a failed index search.\n\t * @since 2.1\n\t */\n\tpublic static final int INDEX_NOT_FOUND = -1;\n\n\tprivate StringUtils() {\n\t}\n\n\t/**\n\t * <p>\n\t * Checks if a CharSequence is empty (\"\") or null.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.isEmpty(null)      = true\n\t * StringUtils.isEmpty(\"\")        = true\n\t * StringUtils.isEmpty(\" \")       = false\n\t * StringUtils.isEmpty(\"bob\")     = false\n\t * StringUtils.isEmpty(\"  bob  \") = false\n\t * </pre>\n\t *\n\t * <p>\n\t * NOTE: This method changed in Lang version 2.0. It no longer trims the CharSequence.\n\t * That functionality is available in isBlank().\n\t * </p>\n\t * @param cs the CharSequence to check, may be null\n\t * @return {@code true} if the CharSequence is empty or null\n\t * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)\n\t */\n\tpublic static boolean isEmpty(final CharSequence cs) {\n\t\treturn cs == null || cs.length() == 0;\n\t}\n\n\t/**\n\t * <p>\n\t * Checks if a CharSequence is not empty (\"\") and not null.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.isNotEmpty(null)      = false\n\t * StringUtils.isNotEmpty(\"\")        = false\n\t * StringUtils.isNotEmpty(\" \")       = true\n\t * StringUtils.isNotEmpty(\"bob\")     = true\n\t * StringUtils.isNotEmpty(\"  bob  \") = true\n\t * </pre>\n\t * @param cs the CharSequence to check, may be null\n\t * @return {@code true} if the CharSequence is not empty and not null\n\t * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence)\n\t */\n\tpublic static boolean isNotEmpty(final CharSequence cs) {\n\t\treturn !isEmpty(cs);\n\t}\n\n\t/**\n\t * <p>\n\t * Checks if a CharSequence is whitespace, empty (\"\") or null.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.isBlank(null)      = true\n\t * StringUtils.isBlank(\"\")        = true\n\t * StringUtils.isBlank(\" \")       = true\n\t * StringUtils.isBlank(\"bob\")     = false\n\t * StringUtils.isBlank(\"  bob  \") = false\n\t * </pre>\n\t * @param cs the CharSequence to check, may be null\n\t * @return {@code true} if the CharSequence is null, empty or whitespace\n\t */\n\tpublic static boolean isBlank(final CharSequence cs) {\n\t\tif (cs == null || cs.length() == 0) {\n\t\t\treturn true;\n\t\t}\n\t\tint strLen = cs.length();\n\t\tfor (int i = 0; i < strLen; i++) {\n\t\t\tif (!Character.isWhitespace(cs.charAt(i))) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * <p>\n\t * Checks if a CharSequence is not empty (\"\"), not null and not whitespace only.\n\t * </p>\n\t *\n\t * <p>\n\t * Whitespace is defined by {@link Character#isWhitespace(char)}.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.isNotBlank(null)      = false\n\t * StringUtils.isNotBlank(\"\")        = false\n\t * StringUtils.isNotBlank(\" \")       = false\n\t * StringUtils.isNotBlank(\"bob\")     = true\n\t * StringUtils.isNotBlank(\"  bob  \") = true\n\t * </pre>\n\t * @param cs the CharSequence to check, may be null\n\t * @return {@code true} if the CharSequence is not empty and not null and not\n\t * whitespace only\n\t * @since 2.0\n\t * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence)\n\t */\n\tpublic static boolean isNotBlank(final CharSequence cs) {\n\t\treturn !isBlank(cs);\n\t}\n\n\t// Trim\n\t// -----------------------------------------------------------------------\n\n\t/**\n\t * <p>\n\t * Removes control characters (char &lt;= 32) from both ends of this String, handling\n\t * {@code null} by returning {@code null}.\n\t * </p>\n\t *\n\t * <p>\n\t * The String is trimmed using {@link String#trim()}. Trim removes start and end\n\t * characters &lt;= 32.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.trim(null)          = null\n\t * StringUtils.trim(\"\")            = \"\"\n\t * StringUtils.trim(\"     \")       = \"\"\n\t * StringUtils.trim(\"abc\")         = \"abc\"\n\t * StringUtils.trim(\"    abc    \") = \"abc\"\n\t * </pre>\n\t * @param str the String to be trimmed, may be null\n\t * @return the trimmed string, {@code null} if null String input\n\t */\n\tpublic static String trim(final String str) {\n\t\treturn str == null ? null : str.trim();\n\t}\n\n\t// Equals\n\t// -----------------------------------------------------------------------\n\n\t/**\n\t * <p>\n\t * Compares two CharSequences, returning {@code true} if they represent equal\n\t * sequences of characters.\n\t * </p>\n\t *\n\t * <p>\n\t * {@code null}s are handled without exceptions. Two {@code null} references are\n\t * considered to be equal. The comparison is case sensitive.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.equals(null, null)   = true\n\t * StringUtils.equals(null, \"abc\")  = false\n\t * StringUtils.equals(\"abc\", null)  = false\n\t * StringUtils.equals(\"abc\", \"abc\") = true\n\t * StringUtils.equals(\"abc\", \"ABC\") = false\n\t * </pre>\n\t * @param cs1 the first CharSequence, may be {@code null}\n\t * @param cs2 the second CharSequence, may be {@code null}\n\t * @return {@code true} if the CharSequences are equal (case-sensitive), or both\n\t * {@code null}\n\t * @see Object#equals(Object)\n\t */\n\tpublic static boolean equals(final CharSequence cs1, final CharSequence cs2) {\n\t\tif (cs1 == cs2) {\n\t\t\treturn true;\n\t\t}\n\t\tif (cs1 == null || cs2 == null) {\n\t\t\treturn false;\n\t\t}\n\t\tif (cs1 instanceof String && cs2 instanceof String) {\n\t\t\treturn cs1.equals(cs2);\n\t\t}\n\t\treturn StringUtils.regionMatches(cs1, false, 0, cs2, 0,\n\t\t\t\tMath.max(cs1.length(), cs2.length()));\n\t}\n\n\t/**\n\t * Green implementation of regionMatches.\n\t * @param cs the {@code CharSequence} to be processed\n\t * @param ignoreCase whether or not to be case insensitive\n\t * @param thisStart the index to start on the {@code cs} CharSequence\n\t * @param substring the {@code CharSequence} to be looked for\n\t * @param start the index to start on the {@code substring} CharSequence\n\t * @param length character length of the region\n\t * @return whether the region matched\n\t */\n\tpublic static boolean regionMatches(final CharSequence cs, final boolean ignoreCase,\n\t\t\tfinal int thisStart, final CharSequence substring, final int start,\n\t\t\tfinal int length) {\n\t\tif (cs instanceof String && substring instanceof String) {\n\t\t\treturn ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring,\n\t\t\t\t\tstart, length);\n\t\t}\n\t\tint index1 = thisStart;\n\t\tint index2 = start;\n\t\tint tmpLen = length;\n\n\t\twhile (tmpLen-- > 0) {\n\t\t\tfinal char c1 = cs.charAt(index1++);\n\t\t\tfinal char c2 = substring.charAt(index2++);\n\n\t\t\tif (c1 == c2) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!ignoreCase) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// The same check as in String.regionMatches():\n\t\t\tif (Character.toUpperCase(c1) != Character.toUpperCase(c2)\n\t\t\t\t\t&& Character.toLowerCase(c1) != Character.toLowerCase(c2)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * <p>\n\t * Gets the substring after the first occurrence of a separator. The separator is not\n\t * returned.\n\t * </p>\n\t *\n\t * <p>\n\t * A <code>null</code> string input will return <code>null</code>. An empty (\"\")\n\t * string input will return the empty string. A <code>null</code> separator will\n\t * return the empty string if the input string is not <code>null</code>.\n\t * </p>\n\t *\n\t * <p>\n\t * If nothing is found, the empty string is returned.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.substringAfter(null, *)      = null\n\t * StringUtils.substringAfter(\"\", *)        = \"\"\n\t * StringUtils.substringAfter(*, null)      = \"\"\n\t * StringUtils.substringAfter(\"abc\", \"a\")   = \"bc\"\n\t * StringUtils.substringAfter(\"abcba\", \"b\") = \"cba\"\n\t * StringUtils.substringAfter(\"abc\", \"c\")   = \"\"\n\t * StringUtils.substringAfter(\"abc\", \"d\")   = \"\"\n\t * StringUtils.substringAfter(\"abc\", \"\")    = \"abc\"\n\t * </pre>\n\t * @param str the String to get a substring from, may be null\n\t * @param separator the String to search for, may be null\n\t * @return the substring after the first occurrence of the separator,\n\t * <code>null</code> if null String input\n\t * @since 2.0\n\t */\n\tpublic static String substringAfter(String str, String separator) {\n\t\tif (isEmpty(str)) {\n\t\t\treturn str;\n\t\t}\n\t\tif (separator == null) {\n\t\t\treturn EMPTY;\n\t\t}\n\t\tint pos = str.indexOf(separator);\n\t\tif (pos == INDEX_NOT_FOUND) {\n\t\t\treturn EMPTY;\n\t\t}\n\t\treturn str.substring(pos + separator.length());\n\t}\n\n\t// Substring between\n\t// -----------------------------------------------------------------------\n\t/**\n\t * <p>\n\t * Gets the String that is nested in between two instances of the same String.\n\t * </p>\n\t *\n\t * <p>\n\t * A <code>null</code> input String returns <code>null</code>. A <code>null</code> tag\n\t * returns <code>null</code>.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.substringBetween(null, *)            = null\n\t * StringUtils.substringBetween(\"\", \"\")             = \"\"\n\t * StringUtils.substringBetween(\"\", \"tag\")          = null\n\t * StringUtils.substringBetween(\"tagabctag\", null)  = null\n\t * StringUtils.substringBetween(\"tagabctag\", \"\")    = \"\"\n\t * StringUtils.substringBetween(\"tagabctag\", \"tag\") = \"abc\"\n\t * </pre>\n\t * @param str the String containing the substring, may be null\n\t * @param tag the String before and after the substring, may be null\n\t * @return the substring, <code>null</code> if no match\n\t * @since 2.0\n\t */\n\tpublic static String substringBetween(String str, String tag) {\n\t\treturn substringBetween(str, tag, tag);\n\t}\n\n\t/**\n\t * <p>\n\t * Gets the String that is nested in between two Strings. Only the first match is\n\t * returned.\n\t * </p>\n\t *\n\t * <p>\n\t * A <code>null</code> input String returns <code>null</code>. A <code>null</code>\n\t * open/close returns <code>null</code> (no match). An empty (\"\") open and close\n\t * returns an empty string.\n\t * </p>\n\t *\n\t * <pre>\n\t * StringUtils.substringBetween(\"wx[b]yz\", \"[\", \"]\") = \"b\"\n\t * StringUtils.substringBetween(null, *, *)          = null\n\t * StringUtils.substringBetween(*, null, *)          = null\n\t * StringUtils.substringBetween(*, *, null)          = null\n\t * StringUtils.substringBetween(\"\", \"\", \"\")          = \"\"\n\t * StringUtils.substringBetween(\"\", \"\", \"]\")         = null\n\t * StringUtils.substringBetween(\"\", \"[\", \"]\")        = null\n\t * StringUtils.substringBetween(\"yabcz\", \"\", \"\")     = \"\"\n\t * StringUtils.substringBetween(\"yabcz\", \"y\", \"z\")   = \"abc\"\n\t * StringUtils.substringBetween(\"yabczyabcz\", \"y\", \"z\")   = \"abc\"\n\t * </pre>\n\t * @param str the String containing the substring, may be null\n\t * @param open the String before the substring, may be null\n\t * @param close the String after the substring, may be null\n\t * @return the substring, <code>null</code> if no match\n\t * @since 2.0\n\t */\n\tpublic static String substringBetween(String str, String open, String close) {\n\t\tif (str == null || open == null || close == null) {\n\t\t\treturn null;\n\t\t}\n\t\tint start = str.indexOf(open);\n\t\tif (start != INDEX_NOT_FOUND) {\n\t\t\tint end = str.indexOf(close, start + open.length());\n\t\t\tif (end != INDEX_NOT_FOUND) {\n\t\t\t\treturn str.substring(start + open.length(), end);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-starters</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>\n    <name>Spring Cloud Alibaba Sentinel DataSource</name>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-alibaba-commons</artifactId>\n        </dependency>\n\n        <!--spring boot -->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-configuration-processor</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-autoconfigure</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.hibernate.validator</groupId>\n            <artifactId>hibernate-validator</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-datasource-extension</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-parameter-flow-control</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-api-gateway-adapter-common</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-datasource-nacos</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-datasource-zookeeper</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-datasource-apollo</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-datasource-redis</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-datasource-consul</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>tools.jackson.core</groupId>\n            <artifactId>jackson-databind</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>tools.jackson.dataformat</groupId>\n            <artifactId>jackson-dataformat-xml</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/RuleType.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource;\n\nimport java.util.Arrays;\nimport java.util.Optional;\n\nimport com.alibaba.cloud.commons.lang.StringUtils;\nimport com.alibaba.cloud.sentinel.datasource.config.AbstractDataSourceProperties;\nimport com.alibaba.csp.sentinel.slots.block.AbstractRule;\nimport com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;\nimport com.alibaba.csp.sentinel.slots.system.SystemRule;\n\n/**\n * Enum for {@link AbstractRule} class, using in\n * {@link AbstractDataSourceProperties#ruleType}.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic enum RuleType {\n\n\t/**\n\t * flow.\n\t */\n\tFLOW(\"flow\", FlowRule.class),\n\t/**\n\t * degrade.\n\t */\n\tDEGRADE(\"degrade\", DegradeRule.class),\n\t/**\n\t * param flow.\n\t */\n\tPARAM_FLOW(\"param-flow\", ParamFlowRule.class),\n\t/**\n\t * system.\n\t */\n\tSYSTEM(\"system\", SystemRule.class),\n\t/**\n\t * authority.\n\t */\n\tAUTHORITY(\"authority\", AuthorityRule.class),\n\t/**\n\t * gateway flow.\n\t */\n\tGW_FLOW(\"gw-flow\",\n\t\t\t\"com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule\"),\n\t/**\n\t * api.\n\t */\n\tGW_API_GROUP(\"gw-api-group\",\n\t\t\t\"com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition\");\n\n\t/**\n\t * alias for {@link AbstractRule}.\n\t */\n\tprivate final String name;\n\n\t/**\n\t * concrete {@link AbstractRule} class.\n\t */\n\tprivate Class clazz;\n\n\t/**\n\t * concrete {@link AbstractRule} class name.\n\t */\n\tprivate String clazzName;\n\n\tRuleType(String name, Class clazz) {\n\t\tthis.name = name;\n\t\tthis.clazz = clazz;\n\t}\n\n\tRuleType(String name, String clazzName) {\n\t\tthis.name = name;\n\t\tthis.clazzName = clazzName;\n\t}\n\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\tpublic Class getClazz() {\n\t\tif (clazz != null) {\n\t\t\treturn clazz;\n\t\t}\n\t\telse {\n\t\t\ttry {\n\t\t\t\treturn Class.forName(clazzName);\n\t\t\t}\n\t\t\tcatch (ClassNotFoundException e) {\n\t\t\t\tthrow new RuntimeException(e);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static Optional<RuleType> getByName(String name) {\n\t\tif (StringUtils.isEmpty(name)) {\n\t\t\treturn Optional.empty();\n\t\t}\n\t\treturn Arrays.stream(RuleType.values())\n\t\t\t\t.filter(ruleType -> name.equals(ruleType.getName())).findFirst();\n\t}\n\n\tpublic static Optional<RuleType> getByClass(Class clazz) {\n\t\treturn Arrays.stream(RuleType.values())\n\t\t\t\t.filter(ruleType -> clazz == ruleType.getClazz()).findFirst();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/AbstractDataSourceProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource.config;\n\n\nimport com.alibaba.cloud.sentinel.datasource.RuleType;\nimport com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;\nimport com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;\nimport com.alibaba.csp.sentinel.datasource.AbstractDataSource;\nimport com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;\nimport com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;\nimport com.alibaba.csp.sentinel.slots.system.SystemRuleManager;\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport jakarta.validation.constraints.NotEmpty;\nimport jakarta.validation.constraints.NotNull;\n\nimport org.springframework.core.env.Environment;\n\n/**\n * Abstract class Using by {@link DataSourcePropertiesConfiguration}.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class AbstractDataSourceProperties {\n\n\t@NotEmpty\n\tprivate String dataType = \"json\";\n\n\t@NotNull\n\tprivate RuleType ruleType;\n\n\tprivate String converterClass;\n\n\t@JsonIgnore\n\tprivate final String factoryBeanName;\n\n\t@JsonIgnore\n\tprivate Environment env;\n\n\tpublic AbstractDataSourceProperties(String factoryBeanName) {\n\t\tthis.factoryBeanName = factoryBeanName;\n\t}\n\n\tpublic String getDataType() {\n\t\treturn dataType;\n\t}\n\n\tpublic void setDataType(String dataType) {\n\t\tthis.dataType = dataType;\n\t}\n\n\tpublic RuleType getRuleType() {\n\t\treturn ruleType;\n\t}\n\n\tpublic void setRuleType(RuleType ruleType) {\n\t\tthis.ruleType = ruleType;\n\t}\n\n\tpublic String getConverterClass() {\n\t\treturn converterClass;\n\t}\n\n\tpublic void setConverterClass(String converterClass) {\n\t\tthis.converterClass = converterClass;\n\t}\n\n\tpublic String getFactoryBeanName() {\n\t\treturn factoryBeanName;\n\t}\n\n\tprotected Environment getEnv() {\n\t\treturn env;\n\t}\n\n\tpublic void setEnv(Environment env) {\n\t\tthis.env = env;\n\t}\n\n\tpublic void preCheck(String dataSourceName) {\n\n\t}\n\n\tpublic void postRegister(AbstractDataSource dataSource) {\n\t\tswitch (this.getRuleType()) {\n\t\tcase FLOW -> FlowRuleManager.register2Property(dataSource.getProperty());\n\t\tcase DEGRADE -> DegradeRuleManager.register2Property(dataSource.getProperty());\n\t\tcase PARAM_FLOW -> ParamFlowRuleManager.register2Property(dataSource.getProperty());\n\t\tcase SYSTEM -> SystemRuleManager.register2Property(dataSource.getProperty());\n\t\tcase AUTHORITY -> AuthorityRuleManager.register2Property(dataSource.getProperty());\n\t\tcase GW_FLOW -> GatewayRuleManager.register2Property(dataSource.getProperty());\n\t\tcase GW_API_GROUP -> GatewayApiDefinitionManager.register2Property(dataSource.getProperty());\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/ApolloDataSourceProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource.config;\n\n\nimport com.alibaba.cloud.sentinel.datasource.factorybean.ApolloDataSourceFactoryBean;\nimport jakarta.validation.constraints.NotEmpty;\n\n/**\n * Apollo Properties class Using by {@link DataSourcePropertiesConfiguration} and\n * {@link ApolloDataSourceFactoryBean}.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class ApolloDataSourceProperties extends AbstractDataSourceProperties {\n\n\t@NotEmpty\n\tprivate String namespaceName;\n\n\t@NotEmpty\n\tprivate String flowRulesKey;\n\n\tprivate String defaultFlowRuleValue;\n\n\tpublic ApolloDataSourceProperties() {\n\t\tsuper(ApolloDataSourceFactoryBean.class.getName());\n\t}\n\n\tpublic String getNamespaceName() {\n\t\treturn namespaceName;\n\t}\n\n\tpublic void setNamespaceName(String namespaceName) {\n\t\tthis.namespaceName = namespaceName;\n\t}\n\n\tpublic String getFlowRulesKey() {\n\t\treturn flowRulesKey;\n\t}\n\n\tpublic void setFlowRulesKey(String flowRulesKey) {\n\t\tthis.flowRulesKey = flowRulesKey;\n\t}\n\n\tpublic String getDefaultFlowRuleValue() {\n\t\treturn defaultFlowRuleValue;\n\t}\n\n\tpublic void setDefaultFlowRuleValue(String defaultFlowRuleValue) {\n\t\tthis.defaultFlowRuleValue = defaultFlowRuleValue;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/ConsulDataSourceProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource.config;\n\nimport com.alibaba.cloud.commons.lang.StringUtils;\nimport com.alibaba.cloud.sentinel.datasource.factorybean.ConsulDataSourceFactoryBean;\n\n\n/**\n * Consul Properties class Using by {@link DataSourcePropertiesConfiguration} and\n * {@link ConsulDataSourceFactoryBean}.\n *\n * @author <a href=\"mailto:mengjindc@gmail.com\">mengjin</a>\n */\npublic class ConsulDataSourceProperties extends AbstractDataSourceProperties {\n\n\tpublic ConsulDataSourceProperties() {\n\t\tsuper(ConsulDataSourceFactoryBean.class.getName());\n\t}\n\n\t/**\n\t * consul server host.\n\t */\n\tprivate String host;\n\n\t/**\n\t * consul server port.\n\t */\n\tprivate int port = 8500;\n\n\t/**\n\t * consul acl-token.\n\t */\n\n\tprivate String token;\n\n\t/**\n\t * data key in Redis.\n\t */\n\tprivate String ruleKey;\n\n\t/**\n\t * Request of query will hang until timeout (in second) or get updated value.\n\t */\n\tprivate int waitTimeoutInSecond = 1;\n\n\t@Override\n\tpublic void preCheck(String dataSourceName) {\n\t\tif (StringUtils.isEmpty(host)) {\n\t\t\tthrow new IllegalArgumentException(\"ConsulDataSource server-host is empty\");\n\t\t}\n\t\tif (StringUtils.isEmpty(ruleKey)) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"ConsulDataSource ruleKey can not be empty\");\n\t\t}\n\t}\n\n\tpublic String getHost() {\n\t\treturn host;\n\t}\n\n\tpublic void setHost(String host) {\n\t\tthis.host = host;\n\t}\n\n\tpublic int getPort() {\n\t\treturn port;\n\t}\n\n\tpublic void setPort(int port) {\n\t\tthis.port = port;\n\t}\n\n\tpublic String getRuleKey() {\n\t\treturn ruleKey;\n\t}\n\n\tpublic void setRuleKey(String ruleKey) {\n\t\tthis.ruleKey = ruleKey;\n\t}\n\n\tpublic int getWaitTimeoutInSecond() {\n\t\treturn waitTimeoutInSecond;\n\t}\n\n\tpublic void setWaitTimeoutInSecond(int waitTimeoutInSecond) {\n\t\tthis.waitTimeoutInSecond = waitTimeoutInSecond;\n\t}\n\n\tpublic String getToken() {\n\t\treturn token;\n\t}\n\n\tpublic void setToken(String token) {\n\t\tthis.token = token;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/DataSourcePropertiesConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource.config;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\n\nimport org.springframework.util.ObjectUtils;\n\n/**\n * Using By ConfigurationProperties.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n * @see NacosDataSourceProperties\n * @see ApolloDataSourceProperties\n * @see ZookeeperDataSourceProperties\n * @see FileDataSourceProperties\n * @see RedisDataSourceProperties\n * @see ConsulDataSourceProperties\n */\npublic class DataSourcePropertiesConfiguration {\n\n\tprivate FileDataSourceProperties file;\n\n\tprivate NacosDataSourceProperties nacos;\n\n\tprivate ZookeeperDataSourceProperties zk;\n\n\tprivate ApolloDataSourceProperties apollo;\n\n\tprivate RedisDataSourceProperties redis;\n\n\tprivate ConsulDataSourceProperties consul;\n\n\tpublic DataSourcePropertiesConfiguration() {\n\t}\n\n\tpublic DataSourcePropertiesConfiguration(ConsulDataSourceProperties consul) {\n\t\tthis.consul = consul;\n\t}\n\n\tpublic ConsulDataSourceProperties getConsul() {\n\t\treturn consul;\n\t}\n\n\tpublic void setConsul(ConsulDataSourceProperties consul) {\n\t\tthis.consul = consul;\n\t}\n\n\tpublic DataSourcePropertiesConfiguration(FileDataSourceProperties file) {\n\t\tthis.file = file;\n\t}\n\n\tpublic DataSourcePropertiesConfiguration(NacosDataSourceProperties nacos) {\n\t\tthis.nacos = nacos;\n\t}\n\n\tpublic DataSourcePropertiesConfiguration(ZookeeperDataSourceProperties zk) {\n\t\tthis.zk = zk;\n\t}\n\n\tpublic DataSourcePropertiesConfiguration(ApolloDataSourceProperties apollo) {\n\t\tthis.apollo = apollo;\n\t}\n\n\tpublic DataSourcePropertiesConfiguration(RedisDataSourceProperties redis) {\n\t\tthis.redis = redis;\n\t}\n\n\tpublic FileDataSourceProperties getFile() {\n\t\treturn file;\n\t}\n\n\tpublic void setFile(FileDataSourceProperties file) {\n\t\tthis.file = file;\n\t}\n\n\tpublic NacosDataSourceProperties getNacos() {\n\t\treturn nacos;\n\t}\n\n\tpublic void setNacos(NacosDataSourceProperties nacos) {\n\t\tthis.nacos = nacos;\n\t}\n\n\tpublic ZookeeperDataSourceProperties getZk() {\n\t\treturn zk;\n\t}\n\n\tpublic void setZk(ZookeeperDataSourceProperties zk) {\n\t\tthis.zk = zk;\n\t}\n\n\tpublic ApolloDataSourceProperties getApollo() {\n\t\treturn apollo;\n\t}\n\n\tpublic void setApollo(ApolloDataSourceProperties apollo) {\n\t\tthis.apollo = apollo;\n\t}\n\n\tpublic RedisDataSourceProperties getRedis() {\n\t\treturn redis;\n\t}\n\n\tpublic void setRedis(RedisDataSourceProperties redis) {\n\t\tthis.redis = redis;\n\t}\n\n\t@JsonIgnore\n\tpublic List<String> getValidField() {\n\t\treturn Arrays\n\t\t\t\t.stream(this.getClass().getDeclaredFields())\n\t\t\t\t.filter(field -> !field.isSynthetic())\n\t\t\t\t.map(field -> {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!ObjectUtils.isEmpty(field.get(this))) {\n\t\t\t\t\t\t\treturn field.getName();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcatch (IllegalAccessException e) {\n\t\t\t\t\t\t// won't happen\n\t\t\t\t\t}\n\t\t\t\t\treturn null;\n\t\t\t\t})\n\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t.collect(Collectors.toList());\n\t}\n\n\t@JsonIgnore\n\tpublic AbstractDataSourceProperties getValidDataSourceProperties() {\n\t\tList<String> invalidFields = getValidField();\n\t\tif (invalidFields.size() == 1) {\n\t\t\ttry {\n\t\t\t\tthis.getClass().getDeclaredField(invalidFields.get(0))\n\t\t\t\t\t\t.setAccessible(true);\n\t\t\t\treturn (AbstractDataSourceProperties) this.getClass()\n\t\t\t\t\t\t.getDeclaredField(invalidFields.get(0)).get(this);\n\t\t\t}\n\t\t\tcatch (IllegalAccessException e) {\n\t\t\t\t// won't happen\n\t\t\t}\n\t\t\tcatch (NoSuchFieldException e) {\n\t\t\t\t// won't happen\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/FileDataSourceProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource.config;\n\nimport java.io.IOException;\n\nimport com.alibaba.cloud.sentinel.datasource.factorybean.FileRefreshableDataSourceFactoryBean;\nimport jakarta.validation.constraints.NotEmpty;\n\nimport org.springframework.util.ResourceUtils;\nimport org.springframework.util.StringUtils;\n\n/**\n * File Properties class Using by {@link DataSourcePropertiesConfiguration} and\n * {@link FileRefreshableDataSourceFactoryBean}.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class FileDataSourceProperties extends AbstractDataSourceProperties {\n\n\t@NotEmpty\n\tprivate String file;\n\n\tprivate String charset = \"utf-8\";\n\n\tprivate long recommendRefreshMs = 3000L;\n\n\tprivate int bufSize = 1024 * 1024;\n\n\tpublic FileDataSourceProperties() {\n\t\tsuper(FileRefreshableDataSourceFactoryBean.class.getName());\n\t}\n\n\tpublic String getFile() {\n\t\treturn file;\n\t}\n\n\tpublic void setFile(String file) {\n\t\tthis.file = file;\n\t}\n\n\tpublic String getCharset() {\n\t\treturn charset;\n\t}\n\n\tpublic void setCharset(String charset) {\n\t\tthis.charset = charset;\n\t}\n\n\tpublic long getRecommendRefreshMs() {\n\t\treturn recommendRefreshMs;\n\t}\n\n\tpublic void setRecommendRefreshMs(long recommendRefreshMs) {\n\t\tthis.recommendRefreshMs = recommendRefreshMs;\n\t}\n\n\tpublic int getBufSize() {\n\t\treturn bufSize;\n\t}\n\n\tpublic void setBufSize(int bufSize) {\n\t\tthis.bufSize = bufSize;\n\t}\n\n\t@Override\n\tpublic void preCheck(String dataSourceName) {\n\t\tsuper.preCheck(dataSourceName);\n\t\ttry {\n\t\t\tthis.setFile(\n\t\t\t\t\tResourceUtils.getFile(StringUtils.trimAllWhitespace(this.getFile()))\n\t\t\t\t\t\t\t.getAbsolutePath());\n\t\t}\n\t\tcatch (IOException e) {\n\t\t\tthrow new RuntimeException(\"[Sentinel Starter] DataSource \" + dataSourceName\n\t\t\t\t\t+ \" handle file [\" + this.getFile() + \"] error: \" + e.getMessage(),\n\t\t\t\t\te);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/NacosDataSourceProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource.config;\n\nimport com.alibaba.cloud.commons.lang.StringUtils;\nimport com.alibaba.cloud.sentinel.datasource.factorybean.NacosDataSourceFactoryBean;\nimport jakarta.validation.constraints.NotEmpty;\n\n/**\n * Nacos Properties class Using by {@link DataSourcePropertiesConfiguration} and\n * {@link NacosDataSourceFactoryBean}.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class NacosDataSourceProperties extends AbstractDataSourceProperties {\n\n\tprivate String serverAddr;\n\n\tprivate String contextPath;\n\n\tprivate String username;\n\n\tprivate String password;\n\n\t@NotEmpty\n\tprivate String groupId = \"DEFAULT_GROUP\";\n\n\t@NotEmpty\n\tprivate String dataId;\n\n\tprivate String endpoint;\n\n\tprivate String namespace;\n\n\tprivate String accessKey;\n\n\tprivate String secretKey;\n\n\tpublic NacosDataSourceProperties() {\n\t\tsuper(NacosDataSourceFactoryBean.class.getName());\n\t}\n\n\t@Override\n\tpublic void preCheck(String dataSourceName) {\n\t\tif (StringUtils.isEmpty(serverAddr)) {\n\t\t\tserverAddr = this.getEnv().getProperty(\n\t\t\t\t\t\"spring.cloud.sentinel.datasource.nacos.server-addr\",\n\t\t\t\t\t\"127.0.0.1:8848\");\n\t\t}\n\t}\n\n\tpublic String getServerAddr() {\n\t\treturn serverAddr;\n\t}\n\n\tpublic void setServerAddr(String serverAddr) {\n\t\tthis.serverAddr = serverAddr;\n\t}\n\n\tpublic String getContextPath() {\n\t\treturn contextPath;\n\t}\n\n\tpublic void setContextPath(String contextPath) {\n\t\tthis.contextPath = contextPath;\n\t}\n\n\tpublic String getUsername() {\n\t\treturn username;\n\t}\n\n\tpublic void setUsername(String username) {\n\t\tthis.username = username;\n\t}\n\n\tpublic String getPassword() {\n\t\treturn password;\n\t}\n\n\tpublic void setPassword(String password) {\n\t\tthis.password = password;\n\t}\n\n\tpublic String getGroupId() {\n\t\treturn groupId;\n\t}\n\n\tpublic void setGroupId(String groupId) {\n\t\tthis.groupId = groupId;\n\t}\n\n\tpublic String getDataId() {\n\t\treturn dataId;\n\t}\n\n\tpublic void setDataId(String dataId) {\n\t\tthis.dataId = dataId;\n\t}\n\n\tpublic String getEndpoint() {\n\t\treturn endpoint;\n\t}\n\n\tpublic void setEndpoint(String endpoint) {\n\t\tthis.endpoint = endpoint;\n\t}\n\n\tpublic String getNamespace() {\n\t\treturn namespace;\n\t}\n\n\tpublic void setNamespace(String namespace) {\n\t\tthis.namespace = namespace;\n\t}\n\n\tpublic String getAccessKey() {\n\t\treturn accessKey;\n\t}\n\n\tpublic void setAccessKey(String accessKey) {\n\t\tthis.accessKey = accessKey;\n\t}\n\n\tpublic String getSecretKey() {\n\t\treturn secretKey;\n\t}\n\n\tpublic void setSecretKey(String secretKey) {\n\t\tthis.secretKey = secretKey;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/RedisDataSourceProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource.config;\n\nimport java.time.Duration;\nimport java.util.List;\n\nimport com.alibaba.cloud.commons.lang.StringUtils;\nimport com.alibaba.cloud.sentinel.datasource.factorybean.RedisDataSourceFactoryBean;\n\n\n/**\n * Redis Properties class Using by {@link DataSourcePropertiesConfiguration} and\n * {@link RedisDataSourceFactoryBean}.\n *\n * @author <a href=\"mailto:wangiegie@gmail.com\">lengleng</a>\n */\npublic class RedisDataSourceProperties extends AbstractDataSourceProperties {\n\n\tpublic RedisDataSourceProperties() {\n\t\tsuper(RedisDataSourceFactoryBean.class.getName());\n\t}\n\n\t/**\n\t * redis server host.\n\t */\n\tprivate String host = \"localhost\";\n\n\t/**\n\t * redis server port.\n\t */\n\tprivate int port = 6379;\n\n\t/**\n\t * redis server password.\n\t */\n\tprivate String password;\n\n\t/**\n\t * redis server default select database.\n\t */\n\tprivate int database;\n\n\t/**\n\t * redis server timeout.\n\t */\n\tprivate Duration timeout;\n\n\t/**\n\t * Comma-separated list of \"host:port\" pairs.\n\t */\n\tprivate List<String> nodes;\n\n\t/**\n\t * data key in Redis.\n\t */\n\tprivate String ruleKey;\n\n\t/**\n\t * channel to subscribe in Redis.\n\t */\n\tprivate String channel;\n\n\t/**\n\t * redis sentinel model.\n\t */\n\tprivate String masterId;\n\n\t@Override\n\tpublic void preCheck(String dataSourceName) {\n\t\tsuper.preCheck(dataSourceName);\n\t\tif (StringUtils.isEmpty(ruleKey)) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"RedisDataSource  ruleKey can not be empty\");\n\t\t}\n\n\t\tif (StringUtils.isEmpty(channel)) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"RedisDataSource  channel can not be empty\");\n\t\t}\n\n\t\tif (StringUtils.isEmpty(masterId)) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"RedisDataSource  sentinel model，masterId can not be empty\");\n\t\t}\n\t}\n\n\tpublic String getHost() {\n\t\treturn host;\n\t}\n\n\tpublic void setHost(String host) {\n\t\tthis.host = host;\n\t}\n\n\tpublic int getPort() {\n\t\treturn port;\n\t}\n\n\tpublic void setPort(int port) {\n\t\tthis.port = port;\n\t}\n\n\tpublic String getRuleKey() {\n\t\treturn ruleKey;\n\t}\n\n\tpublic void setRuleKey(String ruleKey) {\n\t\tthis.ruleKey = ruleKey;\n\t}\n\n\tpublic String getChannel() {\n\t\treturn channel;\n\t}\n\n\tpublic void setChannel(String channel) {\n\t\tthis.channel = channel;\n\t}\n\n\tpublic String getPassword() {\n\t\treturn password;\n\t}\n\n\tpublic void setPassword(String password) {\n\t\tthis.password = password;\n\t}\n\n\tpublic int getDatabase() {\n\t\treturn database;\n\t}\n\n\tpublic void setDatabase(int database) {\n\t\tthis.database = database;\n\t}\n\n\tpublic Duration getTimeout() {\n\t\treturn timeout;\n\t}\n\n\tpublic void setTimeout(Duration timeout) {\n\t\tthis.timeout = timeout;\n\t}\n\n\tpublic List<String> getNodes() {\n\t\treturn nodes;\n\t}\n\n\tpublic void setNodes(List<String> nodes) {\n\t\tthis.nodes = nodes;\n\t}\n\n\tpublic String getMasterId() {\n\t\treturn masterId;\n\t}\n\n\tpublic void setMasterId(String masterId) {\n\t\tthis.masterId = masterId;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/ZookeeperDataSourceProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource.config;\n\nimport com.alibaba.cloud.commons.lang.StringUtils;\nimport com.alibaba.cloud.sentinel.datasource.factorybean.ZookeeperDataSourceFactoryBean;\n\n\n/**\n * Zookeeper Properties class Using by {@link DataSourcePropertiesConfiguration} and\n * {@link ZookeeperDataSourceFactoryBean}.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class ZookeeperDataSourceProperties extends AbstractDataSourceProperties {\n\n\tpublic ZookeeperDataSourceProperties() {\n\t\tsuper(ZookeeperDataSourceFactoryBean.class.getName());\n\t}\n\n\tprivate String serverAddr = \"localhost:2181\";\n\n\tprivate String path;\n\n\tprivate String groupId;\n\n\tprivate String dataId;\n\n\t@Override\n\tpublic void preCheck(String dataSourceName) {\n\t\tif (StringUtils.isEmpty(serverAddr)) {\n\t\t\tserverAddr = this.getEnv()\n\t\t\t\t\t.getProperty(\"spring.cloud.sentinel.datasource.zk.server-addr\", \"\");\n\t\t\tif (StringUtils.isEmpty(serverAddr)) {\n\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"ZookeeperDataSource server-addr is empty\");\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic String getServerAddr() {\n\t\treturn serverAddr;\n\t}\n\n\tpublic void setServerAddr(String serverAddr) {\n\t\tthis.serverAddr = serverAddr;\n\t}\n\n\tpublic String getPath() {\n\t\treturn path;\n\t}\n\n\tpublic void setPath(String path) {\n\t\tthis.path = path;\n\t}\n\n\tpublic String getGroupId() {\n\t\treturn groupId;\n\t}\n\n\tpublic void setGroupId(String groupId) {\n\t\tthis.groupId = groupId;\n\t}\n\n\tpublic String getDataId() {\n\t\treturn dataId;\n\t}\n\n\tpublic void setDataId(String dataId) {\n\t\tthis.dataId = dataId;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/converter/JsonConverter.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource.converter;\n\nimport com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;\nimport com.alibaba.csp.sentinel.slots.system.SystemRule;\nimport tools.jackson.databind.ObjectMapper;\n\n/**\n * Convert sentinel rules for json array Using strict mode to parse json.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n * @see FlowRule\n * @see DegradeRule\n * @see SystemRule\n * @see AuthorityRule\n * @see ParamFlowRule\n * @see ObjectMapper\n */\npublic class JsonConverter<T> extends SentinelConverter {\n\n\tpublic JsonConverter(ObjectMapper objectMapper, Class<T> ruleClass) {\n\t\tsuper(objectMapper, ruleClass);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/converter/SentinelConverter.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource.converter;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Optional;\n\nimport com.alibaba.cloud.commons.lang.StringUtils;\nimport com.alibaba.csp.sentinel.datasource.Converter;\nimport com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;\nimport com.alibaba.csp.sentinel.slots.system.SystemRule;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport tools.jackson.core.JacksonException;\nimport tools.jackson.core.type.TypeReference;\nimport tools.jackson.databind.ObjectMapper;\n\n/**\n * Convert sentinel rules for json or xml array Using strict mode to parse json or xml.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n * @see FlowRule\n * @see DegradeRule\n * @see SystemRule\n * @see AuthorityRule\n * @see ParamFlowRule\n * @see ObjectMapper\n */\npublic abstract class SentinelConverter<T extends Object>\n\t\timplements Converter<String, Collection<Object>> {\n\n\tprivate static final Logger log = LoggerFactory.getLogger(SentinelConverter.class);\n\n\tprivate final ObjectMapper objectMapper;\n\n\tprivate final Class<T> ruleClass;\n\n\tpublic SentinelConverter(ObjectMapper objectMapper, Class<T> ruleClass) {\n\t\tthis.objectMapper = objectMapper;\n\t\tthis.ruleClass = ruleClass;\n\t}\n\n\t@Override\n\tpublic Collection<Object> convert(String source) {\n\t\tCollection<Object> ruleCollection;\n\n\t\t// hard code\n\t\tif (ruleClass == FlowRule.class || ruleClass == DegradeRule.class\n\t\t\t\t|| ruleClass == SystemRule.class || ruleClass == AuthorityRule.class\n\t\t\t\t|| ruleClass == ParamFlowRule.class) {\n\t\t\truleCollection = new ArrayList<>();\n\t\t}\n\t\telse {\n\t\t\truleCollection = new HashSet<>();\n\t\t}\n\n\t\tif (StringUtils.isEmpty(source)) {\n\t\t\tlog.info(\"converter can not convert rules because source is empty\");\n\t\t\treturn ruleCollection;\n\t\t}\n\t\ttry {\n\t\t\tList sourceArray = objectMapper.readValue(source,\n\t\t\t\t\tnew TypeReference<List<HashMap>>() {\n\t\t\t\t\t});\n\n\t\t\tfor (Object obj : sourceArray) {\n\t\t\t\ttry {\n\t\t\t\t\tString item = objectMapper.writeValueAsString(obj);\n\t\t\t\t\tOptional.ofNullable(convertRule(item))\n\t\t\t\t\t\t\t.ifPresent(convertRule -> ruleCollection.add(convertRule));\n\t\t\t\t}\n\t\t\t\tcatch (JacksonException e) {\n\t\t\t\t\tlog.error(\"sentinel rule convert error: \" + e.getMessage(), e);\n\t\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\t\"sentinel rule convert error: \" + e.getMessage(), e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tif (e instanceof RuntimeException runtimeException) {\n\t\t\t\tthrow runtimeException;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new RuntimeException(\"convert error: \" + e.getMessage(), e);\n\t\t\t}\n\t\t}\n\t\treturn ruleCollection;\n\t}\n\n\tprivate Object convertRule(String ruleStr) {\n\t\treturn objectMapper.readValue(ruleStr, ruleClass);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/converter/XmlConverter.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource.converter;\n\nimport com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;\nimport com.alibaba.csp.sentinel.slots.system.SystemRule;\nimport tools.jackson.databind.ObjectMapper;\nimport tools.jackson.dataformat.xml.XmlMapper;\n\n/**\n * Convert sentinel rules for xml array Using strict mode to parse xml.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n * @see FlowRule\n * @see DegradeRule\n * @see SystemRule\n * @see AuthorityRule\n * @see ParamFlowRule\n * @see ObjectMapper\n */\npublic class XmlConverter<T> extends SentinelConverter {\n\n\tpublic XmlConverter(XmlMapper xmlMapper, Class<T> ruleClass) {\n\t\tsuper(xmlMapper, ruleClass);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource.factorybean;\n\nimport com.alibaba.csp.sentinel.datasource.Converter;\nimport com.alibaba.csp.sentinel.datasource.apollo.ApolloDataSource;\n\nimport org.springframework.beans.factory.FactoryBean;\n\n/**\n * A {@link FactoryBean} for creating {@link ApolloDataSource} instance.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n * @see ApolloDataSource\n */\npublic class ApolloDataSourceFactoryBean implements FactoryBean<ApolloDataSource> {\n\n\tprivate String namespaceName;\n\n\tprivate String flowRulesKey;\n\n\tprivate String defaultFlowRuleValue;\n\n\tprivate Converter converter;\n\n\t@Override\n\tpublic ApolloDataSource getObject() throws Exception {\n\t\treturn new ApolloDataSource(namespaceName, flowRulesKey, defaultFlowRuleValue,\n\t\t\t\tconverter);\n\t}\n\n\t@Override\n\tpublic Class<?> getObjectType() {\n\t\treturn ApolloDataSource.class;\n\t}\n\n\tpublic String getNamespaceName() {\n\t\treturn namespaceName;\n\t}\n\n\tpublic void setNamespaceName(String namespaceName) {\n\t\tthis.namespaceName = namespaceName;\n\t}\n\n\tpublic String getFlowRulesKey() {\n\t\treturn flowRulesKey;\n\t}\n\n\tpublic void setFlowRulesKey(String flowRulesKey) {\n\t\tthis.flowRulesKey = flowRulesKey;\n\t}\n\n\tpublic String getDefaultFlowRuleValue() {\n\t\treturn defaultFlowRuleValue;\n\t}\n\n\tpublic void setDefaultFlowRuleValue(String defaultFlowRuleValue) {\n\t\tthis.defaultFlowRuleValue = defaultFlowRuleValue;\n\t}\n\n\tpublic Converter getConverter() {\n\t\treturn converter;\n\t}\n\n\tpublic void setConverter(Converter converter) {\n\t\tthis.converter = converter;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/ConsulDataSourceFactoryBean.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource.factorybean;\n\nimport com.alibaba.csp.sentinel.datasource.Converter;\nimport com.alibaba.csp.sentinel.datasource.consul.ConsulDataSource;\n\nimport org.springframework.beans.factory.FactoryBean;\n\n/**\n * A {@link FactoryBean} for creating {@link ConsulDataSource} instance.\n *\n * @author <a href=\"mailto:mengjindc@gmail.com\">mengjin</a>\n * @see ConsulDataSource\n */\npublic class ConsulDataSourceFactoryBean implements FactoryBean<ConsulDataSource> {\n\n\tprivate String host;\n\n\tprivate int port;\n\n\tprivate String ruleKey;\n\n\tprivate String token;\n\n\tprivate int waitTimeoutInSecond;\n\n\tprivate Converter converter;\n\n\t@Override\n\tpublic ConsulDataSource getObject() throws Exception {\n\t\treturn new ConsulDataSource(host, port, token, ruleKey, waitTimeoutInSecond, converter);\n\t}\n\n\t@Override\n\tpublic Class<?> getObjectType() {\n\t\treturn ConsulDataSource.class;\n\t}\n\n\tpublic String getHost() {\n\t\treturn host;\n\t}\n\n\tpublic void setHost(String host) {\n\t\tthis.host = host;\n\t}\n\n\tpublic int getPort() {\n\t\treturn port;\n\t}\n\n\tpublic void setPort(int port) {\n\t\tthis.port = port;\n\t}\n\n\tpublic String getRuleKey() {\n\t\treturn ruleKey;\n\t}\n\n\tpublic void setRuleKey(String ruleKey) {\n\t\tthis.ruleKey = ruleKey;\n\t}\n\n\tpublic int getWaitTimeoutInSecond() {\n\t\treturn waitTimeoutInSecond;\n\t}\n\n\tpublic void setWaitTimeoutInSecond(int waitTimeoutInSecond) {\n\t\tthis.waitTimeoutInSecond = waitTimeoutInSecond;\n\t}\n\n\tpublic Converter getConverter() {\n\t\treturn converter;\n\t}\n\n\tpublic void setConverter(Converter converter) {\n\t\tthis.converter = converter;\n\t}\n\n\tpublic String getToken() {\n\t\treturn token;\n\t}\n\n\tpublic void setToken(String token) {\n\t\tthis.token = token;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource.factorybean;\n\nimport java.io.File;\nimport java.nio.charset.Charset;\n\nimport com.alibaba.csp.sentinel.datasource.Converter;\nimport com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource;\n\nimport org.springframework.beans.factory.FactoryBean;\n\n/**\n * A {@link FactoryBean} for creating {@link FileRefreshableDataSource} instance.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n * @see FileRefreshableDataSource\n */\npublic class FileRefreshableDataSourceFactoryBean\n\t\timplements FactoryBean<FileRefreshableDataSource> {\n\n\tprivate String file;\n\n\tprivate String charset;\n\n\tprivate long recommendRefreshMs;\n\n\tprivate int bufSize;\n\n\tprivate Converter converter;\n\n\t@Override\n\tpublic FileRefreshableDataSource getObject() throws Exception {\n\t\treturn new FileRefreshableDataSource(new File(file), converter,\n\t\t\t\trecommendRefreshMs, bufSize, Charset.forName(charset));\n\t}\n\n\t@Override\n\tpublic Class<?> getObjectType() {\n\t\treturn FileRefreshableDataSource.class;\n\t}\n\n\tpublic String getFile() {\n\t\treturn file;\n\t}\n\n\tpublic void setFile(String file) {\n\t\tthis.file = file;\n\t}\n\n\tpublic String getCharset() {\n\t\treturn charset;\n\t}\n\n\tpublic void setCharset(String charset) {\n\t\tthis.charset = charset;\n\t}\n\n\tpublic long getRecommendRefreshMs() {\n\t\treturn recommendRefreshMs;\n\t}\n\n\tpublic void setRecommendRefreshMs(long recommendRefreshMs) {\n\t\tthis.recommendRefreshMs = recommendRefreshMs;\n\t}\n\n\tpublic int getBufSize() {\n\t\treturn bufSize;\n\t}\n\n\tpublic void setBufSize(int bufSize) {\n\t\tthis.bufSize = bufSize;\n\t}\n\n\tpublic Converter getConverter() {\n\t\treturn converter;\n\t}\n\n\tpublic void setConverter(Converter converter) {\n\t\tthis.converter = converter;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource.factorybean;\n\nimport java.util.Properties;\n\nimport com.alibaba.cloud.commons.lang.StringUtils;\nimport com.alibaba.csp.sentinel.datasource.Converter;\nimport com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;\nimport com.alibaba.nacos.api.PropertyKeyConst;\n\nimport org.springframework.beans.factory.FactoryBean;\n\n/**\n * A {@link FactoryBean} for creating {@link NacosDataSource} instance.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n * @see NacosDataSource\n */\npublic class NacosDataSourceFactoryBean implements FactoryBean<NacosDataSource> {\n\n\tprivate String serverAddr;\n\n\tprivate String contextPath;\n\n\tprivate String username;\n\n\tprivate String password;\n\n\tprivate String groupId;\n\n\tprivate String dataId;\n\n\tprivate Converter converter;\n\n\tprivate String endpoint;\n\n\tprivate String namespace;\n\n\tprivate String accessKey;\n\n\tprivate String secretKey;\n\n\t@Override\n\tpublic NacosDataSource getObject() throws Exception {\n\t\tProperties properties = new Properties();\n\t\tif (!StringUtils.isEmpty(this.serverAddr)) {\n\t\t\tproperties.setProperty(PropertyKeyConst.SERVER_ADDR, this.serverAddr);\n\t\t}\n\t\telse {\n\t\t\tproperties.setProperty(PropertyKeyConst.ENDPOINT, this.endpoint);\n\t\t}\n\n\t\tif (!StringUtils.isEmpty(this.contextPath)) {\n\t\t\tproperties.setProperty(PropertyKeyConst.CONTEXT_PATH, this.contextPath);\n\t\t}\n\t\tif (!StringUtils.isEmpty(this.accessKey)) {\n\t\t\tproperties.setProperty(PropertyKeyConst.ACCESS_KEY, this.accessKey);\n\t\t}\n\t\tif (!StringUtils.isEmpty(this.secretKey)) {\n\t\t\tproperties.setProperty(PropertyKeyConst.SECRET_KEY, this.secretKey);\n\t\t}\n\t\tif (!StringUtils.isEmpty(this.namespace)) {\n\t\t\tproperties.setProperty(PropertyKeyConst.NAMESPACE, this.namespace);\n\t\t}\n\t\tif (!StringUtils.isEmpty(this.username)) {\n\t\t\tproperties.setProperty(PropertyKeyConst.USERNAME, this.username);\n\t\t}\n\t\tif (!StringUtils.isEmpty(this.password)) {\n\t\t\tproperties.setProperty(PropertyKeyConst.PASSWORD, this.password);\n\t\t}\n\t\treturn new NacosDataSource(properties, groupId, dataId, converter);\n\t}\n\n\t@Override\n\tpublic Class<?> getObjectType() {\n\t\treturn NacosDataSource.class;\n\t}\n\n\tpublic String getServerAddr() {\n\t\treturn serverAddr;\n\t}\n\n\tpublic void setServerAddr(String serverAddr) {\n\t\tthis.serverAddr = serverAddr;\n\t}\n\n\tpublic String getContextPath() {\n\t\treturn contextPath;\n\t}\n\n\tpublic void setContextPath(String contextPath) {\n\t\tthis.contextPath = contextPath;\n\t}\n\n\tpublic String getUsername() {\n\t\treturn username;\n\t}\n\n\tpublic void setUsername(String username) {\n\t\tthis.username = username;\n\t}\n\n\tpublic String getPassword() {\n\t\treturn password;\n\t}\n\n\tpublic void setPassword(String password) {\n\t\tthis.password = password;\n\t}\n\n\tpublic String getGroupId() {\n\t\treturn groupId;\n\t}\n\n\tpublic void setGroupId(String groupId) {\n\t\tthis.groupId = groupId;\n\t}\n\n\tpublic String getDataId() {\n\t\treturn dataId;\n\t}\n\n\tpublic void setDataId(String dataId) {\n\t\tthis.dataId = dataId;\n\t}\n\n\tpublic Converter getConverter() {\n\t\treturn converter;\n\t}\n\n\tpublic void setConverter(Converter converter) {\n\t\tthis.converter = converter;\n\t}\n\n\tpublic String getEndpoint() {\n\t\treturn endpoint;\n\t}\n\n\tpublic void setEndpoint(String endpoint) {\n\t\tthis.endpoint = endpoint;\n\t}\n\n\tpublic String getNamespace() {\n\t\treturn namespace;\n\t}\n\n\tpublic void setNamespace(String namespace) {\n\t\tthis.namespace = namespace;\n\t}\n\n\tpublic String getAccessKey() {\n\t\treturn accessKey;\n\t}\n\n\tpublic void setAccessKey(String accessKey) {\n\t\tthis.accessKey = accessKey;\n\t}\n\n\tpublic String getSecretKey() {\n\t\treturn secretKey;\n\t}\n\n\tpublic void setSecretKey(String secretKey) {\n\t\tthis.secretKey = secretKey;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/RedisDataSourceFactoryBean.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource.factorybean;\n\nimport java.time.Duration;\nimport java.util.List;\n\nimport com.alibaba.csp.sentinel.datasource.Converter;\nimport com.alibaba.csp.sentinel.datasource.redis.RedisDataSource;\nimport com.alibaba.csp.sentinel.datasource.redis.config.RedisConnectionConfig;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRule;\n\nimport org.springframework.beans.factory.FactoryBean;\nimport org.springframework.util.Assert;\nimport org.springframework.util.StringUtils;\n\n/**\n * A {@link FactoryBean} for creating {@link RedisDataSource} instance.\n *\n * @author <a href=\"mailto:wangiegie@gmail.com\">lengleng</a>\n * @see RedisDataSource\n */\npublic class RedisDataSourceFactoryBean implements FactoryBean<RedisDataSource> {\n\n\tprivate String host;\n\n\tprivate int port;\n\n\tprivate int database;\n\n\tprivate Duration timeout;\n\n\t/**\n\t * Comma-separated list of \"host:port\" pairs.\n\t */\n\tprivate List<String> nodes;\n\n\tprivate Converter converter;\n\n\t/**\n\t * data key in Redis.\n\t */\n\tprivate String ruleKey;\n\n\t/**\n\t * channel to subscribe in Redis.\n\t */\n\tprivate String channel;\n\n\t/**\n\t * redis server password.\n\t */\n\tprivate String password;\n\n\tprivate String masterId;\n\n\t@Override\n\tpublic RedisDataSource getObject() {\n\t\tRedisConnectionConfig.Builder builder = RedisConnectionConfig.builder();\n\n\t\tif (nodes == null || nodes.isEmpty()) {\n\t\t\tbuilder.withHost(host).withPort(port).withDatabase(database);\n\t\t}\n\t\telse {\n\t\t\tnodes.forEach(node -> {\n\t\t\t\ttry {\n\t\t\t\t\tString[] parts = StringUtils.split(node, \":\");\n\t\t\t\t\tAssert.state(parts.length == 2, \"Must be defined as 'host:port'\");\n\t\t\t\t\tbuilder.withRedisSentinel(parts[0], Integer.parseInt(parts[1]));\n\t\t\t\t}\n\t\t\t\tcatch (RuntimeException ex) {\n\t\t\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\t\t\"Invalid redis sentinel property \" + node, ex);\n\t\t\t\t}\n\t\t\t});\n\t\t\tbuilder.withSentinelMasterId(masterId);\n\t\t}\n\n\t\tif (timeout != null) {\n\t\t\tbuilder.withTimeout(timeout.toMillis());\n\t\t}\n\n\t\tif (StringUtils.hasText(password)) {\n\t\t\tbuilder.withPassword(password);\n\t\t}\n\n\t\treturn new RedisDataSource<List<FlowRule>>(builder.build(), ruleKey, channel,\n\t\t\t\tconverter);\n\t}\n\n\t@Override\n\tpublic Class<?> getObjectType() {\n\t\treturn RedisDataSource.class;\n\t}\n\n\tpublic Converter getConverter() {\n\t\treturn converter;\n\t}\n\n\tpublic void setConverter(Converter converter) {\n\t\tthis.converter = converter;\n\t}\n\n\tpublic String getHost() {\n\t\treturn host;\n\t}\n\n\tpublic void setHost(String host) {\n\t\tthis.host = host;\n\t}\n\n\tpublic int getPort() {\n\t\treturn port;\n\t}\n\n\tpublic void setPort(int port) {\n\t\tthis.port = port;\n\t}\n\n\tpublic String getRuleKey() {\n\t\treturn ruleKey;\n\t}\n\n\tpublic void setRuleKey(String ruleKey) {\n\t\tthis.ruleKey = ruleKey;\n\t}\n\n\tpublic String getChannel() {\n\t\treturn channel;\n\t}\n\n\tpublic void setChannel(String channel) {\n\t\tthis.channel = channel;\n\t}\n\n\tpublic String getPassword() {\n\t\treturn password;\n\t}\n\n\tpublic void setPassword(String password) {\n\t\tthis.password = password;\n\t}\n\n\tpublic int getDatabase() {\n\t\treturn database;\n\t}\n\n\tpublic void setDatabase(int database) {\n\t\tthis.database = database;\n\t}\n\n\tpublic Duration getTimeout() {\n\t\treturn timeout;\n\t}\n\n\tpublic void setTimeout(Duration timeout) {\n\t\tthis.timeout = timeout;\n\t}\n\n\tpublic List<String> getNodes() {\n\t\treturn nodes;\n\t}\n\n\tpublic void setNodes(List<String> nodes) {\n\t\tthis.nodes = nodes;\n\t}\n\n\tpublic String getMasterId() {\n\t\treturn masterId;\n\t}\n\n\tpublic void setMasterId(String masterId) {\n\t\tthis.masterId = masterId;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource.factorybean;\n\nimport com.alibaba.cloud.commons.lang.StringUtils;\nimport com.alibaba.csp.sentinel.datasource.Converter;\nimport com.alibaba.csp.sentinel.datasource.zookeeper.ZookeeperDataSource;\n\nimport org.springframework.beans.factory.FactoryBean;\n\n/**\n * A {@link FactoryBean} for creating {@link ZookeeperDataSource} instance.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n * @see ZookeeperDataSource\n */\npublic class ZookeeperDataSourceFactoryBean implements FactoryBean<ZookeeperDataSource> {\n\n\tprivate String serverAddr;\n\n\tprivate String path;\n\n\tprivate String groupId;\n\n\tprivate String dataId;\n\n\tprivate Converter converter;\n\n\t@Override\n\tpublic ZookeeperDataSource getObject() throws Exception {\n\t\tif (StringUtils.isNotEmpty(groupId) && StringUtils.isNotEmpty(dataId)) {\n\t\t\t// the path will be /{groupId}/{dataId}\n\t\t\treturn new ZookeeperDataSource(serverAddr, groupId, dataId, converter);\n\t\t}\n\t\telse {\n\t\t\t// using path directly\n\t\t\treturn new ZookeeperDataSource(serverAddr, path, converter);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Class<?> getObjectType() {\n\t\treturn ZookeeperDataSource.class;\n\t}\n\n\tpublic String getServerAddr() {\n\t\treturn serverAddr;\n\t}\n\n\tpublic void setServerAddr(String serverAddr) {\n\t\tthis.serverAddr = serverAddr;\n\t}\n\n\tpublic String getPath() {\n\t\treturn path;\n\t}\n\n\tpublic void setPath(String path) {\n\t\tthis.path = path;\n\t}\n\n\tpublic String getGroupId() {\n\t\treturn groupId;\n\t}\n\n\tpublic void setGroupId(String groupId) {\n\t\tthis.groupId = groupId;\n\t}\n\n\tpublic String getDataId() {\n\t\treturn dataId;\n\t}\n\n\tpublic void setDataId(String dataId) {\n\t\tthis.dataId = dataId;\n\t}\n\n\tpublic Converter getConverter() {\n\t\treturn converter;\n\t}\n\n\tpublic void setConverter(Converter converter) {\n\t\tthis.converter = converter;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/resources/META-INF/sentinel-datasource.properties",
    "content": "nacos = com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource\nfile =com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource\napollo = com.alibaba.csp.sentinel.datasource.apollo.ApolloDataSource\nzk = com.alibaba.csp.sentinel.datasource.zookeeper.ZookeeperDataSource\nredis = com.alibaba.csp.sentinel.datasource.redis.RedisDataSource\nconsul = com.alibaba.csp.sentinel.datasource.consul.ConsulDataSource\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/ApolloDataSourceFactoryBeanTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource;\n\nimport com.alibaba.cloud.sentinel.datasource.converter.JsonConverter;\nimport com.alibaba.cloud.sentinel.datasource.factorybean.ApolloDataSourceFactoryBean;\nimport com.alibaba.csp.sentinel.datasource.Converter;\nimport com.alibaba.csp.sentinel.datasource.apollo.ApolloDataSource;\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.Mockito.doReturn;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.spy;\nimport static org.mockito.Mockito.when;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class ApolloDataSourceFactoryBeanTests {\n\n\tprivate String flowRuleKey = \"sentinel\";\n\n\tprivate String namespace = \"namespace\";\n\n\tprivate String defaultFlowValue = \"{}\";\n\n\t@Test\n\tpublic void testApolloFactoryBean() throws Exception {\n\t\tApolloDataSourceFactoryBean factoryBean = spy(new ApolloDataSourceFactoryBean());\n\n\t\tConverter converter = mock(JsonConverter.class);\n\n\t\tfactoryBean.setDefaultFlowRuleValue(defaultFlowValue);\n\t\tfactoryBean.setFlowRulesKey(flowRuleKey);\n\t\tfactoryBean.setNamespaceName(namespace);\n\t\tfactoryBean.setConverter(converter);\n\n\t\tApolloDataSource apolloDataSource = mock(ApolloDataSource.class);\n\n\t\twhen(apolloDataSource.readSource()).thenReturn(\"{}\");\n\t\tdoReturn(apolloDataSource).when(factoryBean).getObject();\n\n\t\tassertThat(factoryBean.getObject()).isEqualTo(apolloDataSource);\n\t\tassertThat(factoryBean.getObject().readSource()).isEqualTo(\"{}\");\n\t\tassertThat(factoryBean.getConverter()).isEqualTo(converter);\n\t\tassertThat(factoryBean.getFlowRulesKey()).isEqualTo(flowRuleKey);\n\t\tassertThat(factoryBean.getNamespaceName()).isEqualTo(namespace);\n\t\tassertThat(factoryBean.getDefaultFlowRuleValue()).isEqualTo(defaultFlowValue);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/DataSourcePropertiesConfigurationTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource;\n\nimport java.util.List;\n\nimport com.alibaba.cloud.sentinel.datasource.config.ApolloDataSourceProperties;\nimport com.alibaba.cloud.sentinel.datasource.config.DataSourcePropertiesConfiguration;\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * Test cases for {@link DataSourcePropertiesConfiguration}.\n *\n * @author <a href=\"mailto:i@5icodes.com\">hnyyghk</a>\n */\npublic class DataSourcePropertiesConfigurationTests {\n\n\t/**\n\t * Test cases for {@link DataSourcePropertiesConfiguration#getValidField()}.\n\t *\n\t * @see com.alibaba.cloud.sentinel.custom.SentinelDataSourceHandler#afterSingletonsInstantiated()\n\t */\n\t@Test\n\tpublic void testGetValidField() {\n\t\tDataSourcePropertiesConfiguration configuration = new DataSourcePropertiesConfiguration();\n\t\tApolloDataSourceProperties apollo = new ApolloDataSourceProperties();\n\t\tapollo.setNamespaceName(\"application\");\n\t\tapollo.setFlowRulesKey(\"test-flow-rules\");\n\t\tapollo.setDefaultFlowRuleValue(\"[]\");\n\t\tapollo.setDataType(\"json\");\n\t\tapollo.setRuleType(RuleType.FLOW);\n\t\tconfiguration.setApollo(apollo);\n\n\t\t//indicate which datasource active\n\t\tList<String> validField = configuration.getValidField();\n\n\t\t//not allowed multi datasource active, $jacocoData should not be included\n\t\tassertThat(validField.size()).isEqualTo(1);\n\t\tassertThat(validField).doesNotContain(\"$jacocoData\");\n\t\tassertThat(validField).contains(\"apollo\");\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/DataSourcePropertiesTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource;\n\nimport java.util.List;\n\nimport com.alibaba.cloud.sentinel.datasource.config.ApolloDataSourceProperties;\nimport com.alibaba.cloud.sentinel.datasource.config.FileDataSourceProperties;\nimport com.alibaba.cloud.sentinel.datasource.config.ZookeeperDataSourceProperties;\nimport com.alibaba.cloud.sentinel.datasource.factorybean.ApolloDataSourceFactoryBean;\nimport com.alibaba.cloud.sentinel.datasource.factorybean.FileRefreshableDataSourceFactoryBean;\nimport com.alibaba.cloud.sentinel.datasource.factorybean.ZookeeperDataSourceFactoryBean;\nimport com.alibaba.csp.sentinel.datasource.Converter;\nimport com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;\nimport org.junit.jupiter.api.Test;\nimport tools.jackson.core.type.TypeReference;\nimport tools.jackson.databind.ObjectMapper;\n\nimport org.springframework.util.ResourceUtils;\nimport org.springframework.util.StringUtils;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatExceptionOfType;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class DataSourcePropertiesTests {\n\n\t@Test\n\tpublic void testApollo() {\n\t\tApolloDataSourceProperties apolloDataSourceProperties = new ApolloDataSourceProperties();\n\t\tapolloDataSourceProperties.setFlowRulesKey(\"test-key\");\n\t\tapolloDataSourceProperties.setDefaultFlowRuleValue(\"dft-val\");\n\t\tapolloDataSourceProperties.setNamespaceName(\"namespace\");\n\t\tapolloDataSourceProperties.setRuleType(RuleType.DEGRADE);\n\n\t\tassertThat(apolloDataSourceProperties.getFlowRulesKey()).isEqualTo(\"test-key\");\n\t\tassertThat(apolloDataSourceProperties.getNamespaceName()).isEqualTo(\"namespace\");\n\t\tassertThat(apolloDataSourceProperties.getDataType()).isEqualTo(\"json\");\n\t\tassertThat(apolloDataSourceProperties.getRuleType()).isEqualTo(RuleType.DEGRADE);\n\t\tassertThat(apolloDataSourceProperties.getDefaultFlowRuleValue())\n\t\t\t\t.isEqualTo(\"dft-val\");\n\t\tassertThat(apolloDataSourceProperties.getFactoryBeanName())\n\t\t\t\t.isEqualTo(ApolloDataSourceFactoryBean.class.getName());\n\t\tassertThat(apolloDataSourceProperties.getConverterClass()).isNull();\n\t}\n\n\t@Test\n\tpublic void testZK() {\n\t\tZookeeperDataSourceProperties zookeeperDataSourceProperties = new ZookeeperDataSourceProperties();\n\n\t\tzookeeperDataSourceProperties.setServerAddr(\"localhost:2181\");\n\t\tzookeeperDataSourceProperties.setGroupId(\"groupId\");\n\t\tzookeeperDataSourceProperties.setDataId(\"dataId\");\n\t\tzookeeperDataSourceProperties.setPath(\"/path\");\n\t\tzookeeperDataSourceProperties.setConverterClass(\"test.ConverterClass\");\n\t\tzookeeperDataSourceProperties.setRuleType(RuleType.AUTHORITY);\n\n\t\tassertThat(zookeeperDataSourceProperties.getServerAddr())\n\t\t\t\t.isEqualTo(\"localhost:2181\");\n\t\tassertThat(zookeeperDataSourceProperties.getGroupId()).isEqualTo(\"groupId\");\n\t\tassertThat(zookeeperDataSourceProperties.getDataId()).isEqualTo(\"dataId\");\n\t\tassertThat(zookeeperDataSourceProperties.getPath()).isEqualTo(\"/path\");\n\t\tassertThat(zookeeperDataSourceProperties.getFactoryBeanName())\n\t\t\t\t.isEqualTo(ZookeeperDataSourceFactoryBean.class.getName());\n\t\tassertThat(zookeeperDataSourceProperties.getConverterClass())\n\t\t\t\t.isEqualTo(\"test.ConverterClass\");\n\t\tassertThat(zookeeperDataSourceProperties.getRuleType())\n\t\t\t\t.isEqualTo(RuleType.AUTHORITY);\n\t}\n\n\t@Test\n\tpublic void testFileDefaultValue() {\n\t\tFileDataSourceProperties fileDataSourceProperties = new FileDataSourceProperties();\n\n\t\tfileDataSourceProperties.setFile(\"/tmp/test.json\");\n\t\tfileDataSourceProperties.setRuleType(RuleType.PARAM_FLOW);\n\n\t\tassertThat(fileDataSourceProperties.getFile()).isEqualTo(\"/tmp/test.json\");\n\t\tassertThat(fileDataSourceProperties.getCharset()).isEqualTo(\"utf-8\");\n\t\tassertThat(fileDataSourceProperties.getRecommendRefreshMs()).isEqualTo(3000L);\n\t\tassertThat(fileDataSourceProperties.getBufSize()).isEqualTo(1024 * 1024);\n\t\tassertThat(fileDataSourceProperties.getFactoryBeanName())\n\t\t\t\t.isEqualTo(FileRefreshableDataSourceFactoryBean.class.getName());\n\t\tassertThat(fileDataSourceProperties.getRuleType()).isEqualTo(RuleType.PARAM_FLOW);\n\t}\n\n\t@Test\n\tpublic void testFileCustomValue() {\n\t\tFileDataSourceProperties fileDataSourceProperties = new FileDataSourceProperties();\n\n\t\tfileDataSourceProperties.setFile(\"/tmp/test.json\");\n\t\tfileDataSourceProperties.setBufSize(1024);\n\t\tfileDataSourceProperties.setRecommendRefreshMs(2000);\n\t\tfileDataSourceProperties.setCharset(\"ISO8859-1\");\n\n\t\tassertThat(fileDataSourceProperties.getFile()).isEqualTo(\"/tmp/test.json\");\n\t\tassertThat(fileDataSourceProperties.getCharset()).isEqualTo(\"ISO8859-1\");\n\t\tassertThat(fileDataSourceProperties.getRecommendRefreshMs()).isEqualTo(2000L);\n\t\tassertThat(fileDataSourceProperties.getBufSize()).isEqualTo(1024);\n\t}\n\n\t@Test\n\tpublic void testFileException() {\n\t\tassertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {\n\t\t\tFileDataSourceProperties fileDataSourceProperties = new FileDataSourceProperties();\n\t\t\tfileDataSourceProperties.setFile(\"classpath: 1.json\");\n\t\t\tfileDataSourceProperties.preCheck(\"test-ds\");\n\t\t});\n\t}\n\n\t@Test\n\tpublic void testPostRegister() throws Exception {\n\t\tFileDataSourceProperties fileDataSourceProperties = new FileDataSourceProperties();\n\n\t\tfileDataSourceProperties.setFile(\"classpath: flowrule.json\");\n\t\tfileDataSourceProperties.setRuleType(RuleType.FLOW);\n\n\t\tFileRefreshableDataSource fileRefreshableDataSource = new FileRefreshableDataSource(\n\t\t\t\tResourceUtils\n\t\t\t\t\t\t.getFile(StringUtils\n\t\t\t\t\t\t\t\t.trimAllWhitespace(fileDataSourceProperties.getFile()))\n\t\t\t\t\t\t.getAbsolutePath(),\n\t\t\t\tnew Converter<String, List<FlowRule>>() {\n\t\t\t\t\tObjectMapper objectMapper = new ObjectMapper();\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic List<FlowRule> convert(String source) {\n\t\t\t\t\t\treturn objectMapper.readValue(source, new TypeReference<>() { });\n\t\t\t\t\t}\n\t\t\t\t});\n\t\tfileDataSourceProperties.postRegister(fileRefreshableDataSource);\n\t\tassertThat(FlowRuleManager.getRules())\n\t\t\t\t.isEqualTo(fileRefreshableDataSource.loadConfig());\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/FileRefreshableDataSourceFactoryBeanTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource;\n\nimport java.io.FileNotFoundException;\nimport java.util.List;\n\nimport com.alibaba.cloud.sentinel.datasource.factorybean.FileRefreshableDataSourceFactoryBean;\nimport com.alibaba.csp.sentinel.datasource.Converter;\nimport com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRule;\nimport org.junit.jupiter.api.Test;\nimport tools.jackson.core.type.TypeReference;\nimport tools.jackson.databind.ObjectMapper;\n\nimport org.springframework.context.annotation.AnnotationConfigApplicationContext;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.util.ResourceUtils;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class FileRefreshableDataSourceFactoryBeanTests {\n\n\t@Test\n\tpublic void testFile() throws Exception {\n\t\tAnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(\n\t\t\t\tTestConfig.class);\n\t\tassertThat(annotationConfigApplicationContext.getBean(\"fileBean\")).isNotNull();\n\t\tFileRefreshableDataSource fileRefreshableDataSource = annotationConfigApplicationContext\n\t\t\t\t.getBean(\"fileBean\", FileRefreshableDataSource.class);\n\t\tassertThat(((List<FlowRule>) fileRefreshableDataSource.loadConfig()).size())\n\t\t\t\t.isEqualTo(1);\n\t\tFileRefreshableDataSourceFactoryBean factoryBean = annotationConfigApplicationContext\n\t\t\t\t.getBean(\"&fileBean\", FileRefreshableDataSourceFactoryBean.class);\n\t\tassertThat(factoryBean.getBufSize()).isEqualTo(1024);\n\t\tassertThat(factoryBean.getCharset()).isEqualTo(\"utf-8\");\n\t\tassertThat(factoryBean.getRecommendRefreshMs()).isEqualTo(2000);\n\t\tassertThat(factoryBean.getFile()).isNotNull();\n\t\tassertThat(factoryBean.getConverter()).isNotNull();\n\t}\n\n\t@Configuration\n\tpublic static class TestConfig {\n\n\t\t@Bean\n\t\tpublic FileRefreshableDataSourceFactoryBean fileBean() {\n\t\t\tFileRefreshableDataSourceFactoryBean factoryBean = new FileRefreshableDataSourceFactoryBean();\n\t\t\tfactoryBean.setBufSize(1024);\n\t\t\tfactoryBean.setCharset(\"utf-8\");\n\t\t\tfactoryBean.setRecommendRefreshMs(2000);\n\t\t\ttry {\n\t\t\t\tfactoryBean.setFile(ResourceUtils.getFile(\"classpath:flowrule.json\")\n\t\t\t\t\t\t.getAbsolutePath());\n\t\t\t}\n\t\t\tcatch (FileNotFoundException e) {\n\t\t\t\t// ignore\n\t\t\t}\n\t\t\tfactoryBean.setConverter(buildConverter());\n\t\t\treturn factoryBean;\n\t\t}\n\n\t\tprivate Converter buildConverter() {\n\t\t\treturn new Converter<String, List<FlowRule>>() {\n\t\t\t\tObjectMapper objectMapper = new ObjectMapper();\n\n\t\t\t\t@Override\n\t\t\t\tpublic List<FlowRule> convert(String source) {\n\t\t\t\t\treturn objectMapper.readValue(source, new TypeReference<>() { });\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/NacosDataSourceFactoryBeanTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource;\n\nimport com.alibaba.cloud.sentinel.datasource.converter.SentinelConverter;\nimport com.alibaba.cloud.sentinel.datasource.factorybean.NacosDataSourceFactoryBean;\nimport com.alibaba.csp.sentinel.datasource.Converter;\nimport com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.Mockito.doReturn;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.spy;\nimport static org.mockito.Mockito.when;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class NacosDataSourceFactoryBeanTests {\n\n\tprivate String dataId = \"sentinel\";\n\n\tprivate String groupId = \"DEFAULT_GROUP\";\n\n\tprivate String serverAddr = \"127.0.0.1:8848\";\n\n\tprivate String contextPath = \"/my-nacos\";\n\n\tprivate String accessKey = \"ak\";\n\n\tprivate String secretKey = \"sk\";\n\n\tprivate String endpoint = \"endpoint\";\n\n\tprivate String namespace = \"namespace\";\n\n\t@Test\n\tpublic void testNacosFactoryBeanServerAddr() throws Exception {\n\t\tNacosDataSourceFactoryBean factoryBean = spy(new NacosDataSourceFactoryBean());\n\n\t\tConverter converter = mock(SentinelConverter.class);\n\n\t\tfactoryBean.setDataId(dataId);\n\t\tfactoryBean.setGroupId(groupId);\n\t\tfactoryBean.setServerAddr(serverAddr);\n\t\tfactoryBean.setContextPath(contextPath);\n\t\tfactoryBean.setConverter(converter);\n\n\t\tNacosDataSource nacosDataSource = mock(NacosDataSource.class);\n\n\t\tdoReturn(nacosDataSource).when(factoryBean).getObject();\n\t\twhen(nacosDataSource.readSource()).thenReturn(\"{}\");\n\n\t\tassertThat(factoryBean.getObject()).isEqualTo(nacosDataSource);\n\t\tassertThat(factoryBean.getObject().readSource()).isEqualTo(\"{}\");\n\t\tassertThat(factoryBean.getConverter()).isEqualTo(converter);\n\t\tassertThat(factoryBean.getDataId()).isEqualTo(dataId);\n\t\tassertThat(factoryBean.getGroupId()).isEqualTo(groupId);\n\t\tassertThat(factoryBean.getServerAddr()).isEqualTo(serverAddr);\n\t\tassertThat(factoryBean.getContextPath()).isEqualTo(contextPath);\n\t}\n\n\t@Test\n\tpublic void testNacosFactoryBeanProperties() throws Exception {\n\t\tNacosDataSourceFactoryBean factoryBean = spy(new NacosDataSourceFactoryBean());\n\n\t\tConverter converter = mock(SentinelConverter.class);\n\n\t\tfactoryBean.setDataId(dataId);\n\t\tfactoryBean.setGroupId(groupId);\n\t\tfactoryBean.setAccessKey(accessKey);\n\t\tfactoryBean.setSecretKey(secretKey);\n\t\tfactoryBean.setEndpoint(endpoint);\n\t\tfactoryBean.setNamespace(namespace);\n\t\tfactoryBean.setConverter(converter);\n\n\t\tNacosDataSource nacosDataSource = mock(NacosDataSource.class);\n\n\t\tdoReturn(nacosDataSource).when(factoryBean).getObject();\n\t\twhen(nacosDataSource.readSource()).thenReturn(\"{}\");\n\n\t\tassertThat(factoryBean.getObject()).isEqualTo(nacosDataSource);\n\t\tassertThat(factoryBean.getObject().readSource()).isEqualTo(\"{}\");\n\t\tassertThat(factoryBean.getConverter()).isEqualTo(converter);\n\t\tassertThat(factoryBean.getDataId()).isEqualTo(dataId);\n\t\tassertThat(factoryBean.getGroupId()).isEqualTo(groupId);\n\t\tassertThat(factoryBean.getNamespace()).isEqualTo(namespace);\n\t\tassertThat(factoryBean.getEndpoint()).isEqualTo(endpoint);\n\t\tassertThat(factoryBean.getAccessKey()).isEqualTo(accessKey);\n\t\tassertThat(factoryBean.getSecretKey()).isEqualTo(secretKey);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/NacosDataSourcePropertiesTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource;\n\nimport com.alibaba.cloud.sentinel.datasource.config.NacosDataSourceProperties;\nimport com.alibaba.cloud.sentinel.datasource.factorybean.NacosDataSourceFactoryBean;\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class NacosDataSourcePropertiesTests {\n\n\t@Test\n\tpublic void testNacosWithAddr() {\n\t\tNacosDataSourceProperties nacosDataSourceProperties = new NacosDataSourceProperties();\n\t\tnacosDataSourceProperties.setServerAddr(\"127.0.0.1:8848\");\n\t\tnacosDataSourceProperties.setContextPath(\"/my-nacos\");\n\t\tnacosDataSourceProperties.setRuleType(RuleType.FLOW);\n\t\tnacosDataSourceProperties.setDataId(\"sentinel\");\n\t\tnacosDataSourceProperties.setGroupId(\"custom-group\");\n\t\tnacosDataSourceProperties.setDataType(\"xml\");\n\n\t\tassertThat(nacosDataSourceProperties.getContextPath()).isEqualTo(\"/my-nacos\");\n\t\tassertThat(nacosDataSourceProperties.getGroupId()).isEqualTo(\"custom-group\");\n\t\tassertThat(nacosDataSourceProperties.getDataId()).isEqualTo(\"sentinel\");\n\t\tassertThat(nacosDataSourceProperties.getDataType()).isEqualTo(\"xml\");\n\t\tassertThat(nacosDataSourceProperties.getRuleType()).isEqualTo(RuleType.FLOW);\n\t\tassertThat(nacosDataSourceProperties.getFactoryBeanName())\n\t\t\t\t.isEqualTo(NacosDataSourceFactoryBean.class.getName());\n\t}\n\n\t@Test\n\tpublic void testNacosWithProperties() {\n\t\tNacosDataSourceProperties nacosDataSourceProperties = new NacosDataSourceProperties();\n\t\tnacosDataSourceProperties.setAccessKey(\"ak\");\n\t\tnacosDataSourceProperties.setSecretKey(\"sk\");\n\t\tnacosDataSourceProperties.setEndpoint(\"endpoint\");\n\t\tnacosDataSourceProperties.setNamespace(\"namespace\");\n\t\tnacosDataSourceProperties.setRuleType(RuleType.SYSTEM);\n\n\t\tassertThat(nacosDataSourceProperties.getAccessKey()).isEqualTo(\"ak\");\n\t\tassertThat(nacosDataSourceProperties.getSecretKey()).isEqualTo(\"sk\");\n\t\tassertThat(nacosDataSourceProperties.getEndpoint()).isEqualTo(\"endpoint\");\n\t\tassertThat(nacosDataSourceProperties.getNamespace()).isEqualTo(\"namespace\");\n\t\tassertThat(nacosDataSourceProperties.getRuleType()).isEqualTo(RuleType.SYSTEM);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/RuleTypeTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource;\n\nimport com.alibaba.csp.sentinel.slots.block.AbstractRule;\nimport com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;\nimport com.alibaba.csp.sentinel.slots.system.SystemRule;\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class RuleTypeTests {\n\n\t@Test\n\tpublic void testGetByName() {\n\t\tassertThat(RuleType.getByName(\"\").isPresent()).isEqualTo(Boolean.FALSE);\n\t\tassertThat(RuleType.getByName(\"test\").isPresent()).isEqualTo(Boolean.FALSE);\n\t\tassertThat(RuleType.getByName(\"param_flow\").isPresent()).isEqualTo(Boolean.FALSE);\n\t\tassertThat(RuleType.getByName(\"param\").isPresent()).isEqualTo(Boolean.FALSE);\n\t\tassertThat(RuleType.getByName(\"FLOW\").isPresent()).isEqualTo(Boolean.FALSE);\n\t\tassertThat(RuleType.getByName(\"flow\").isPresent()).isEqualTo(Boolean.TRUE);\n\t\tassertThat(RuleType.getByName(\"degrade\").isPresent()).isEqualTo(Boolean.TRUE);\n\t\tassertThat(RuleType.getByName(\"param-flow\").isPresent()).isEqualTo(Boolean.TRUE);\n\t\tassertThat(RuleType.getByName(\"system\").isPresent()).isEqualTo(Boolean.TRUE);\n\t\tassertThat(RuleType.getByName(\"authority\").isPresent()).isEqualTo(Boolean.TRUE);\n\t\tassertThat(RuleType.getByName(\"flow\").get()).isEqualTo(RuleType.FLOW);\n\t\tassertThat(RuleType.getByName(\"degrade\").get()).isEqualTo(RuleType.DEGRADE);\n\t\tassertThat(RuleType.getByName(\"param-flow\").get()).isEqualTo(RuleType.PARAM_FLOW);\n\t\tassertThat(RuleType.getByName(\"system\").get()).isEqualTo(RuleType.SYSTEM);\n\t\tassertThat(RuleType.getByName(\"authority\").get()).isEqualTo(RuleType.AUTHORITY);\n\t}\n\n\t@Test\n\tpublic void testGetByClass() {\n\t\tassertThat(RuleType.getByClass(Object.class).isPresent())\n\t\t\t\t.isEqualTo(Boolean.FALSE);\n\t\tassertThat(RuleType.getByClass(AbstractRule.class).isPresent())\n\t\t\t\t.isEqualTo(Boolean.FALSE);\n\t\tassertThat(RuleType.getByClass(FlowRule.class).isPresent())\n\t\t\t\t.isEqualTo(Boolean.TRUE);\n\t\tassertThat(RuleType.getByClass(DegradeRule.class).isPresent())\n\t\t\t\t.isEqualTo(Boolean.TRUE);\n\t\tassertThat(RuleType.getByClass(ParamFlowRule.class).isPresent())\n\t\t\t\t.isEqualTo(Boolean.TRUE);\n\t\tassertThat(RuleType.getByClass(SystemRule.class).isPresent())\n\t\t\t\t.isEqualTo(Boolean.TRUE);\n\t\tassertThat(RuleType.getByClass(AuthorityRule.class).isPresent())\n\t\t\t\t.isEqualTo(Boolean.TRUE);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/SentinelConverterTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource;\n\nimport java.io.IOException;\nimport java.nio.charset.Charset;\nimport java.util.List;\n\nimport com.alibaba.cloud.commons.io.FileUtils;\nimport com.alibaba.cloud.sentinel.datasource.converter.JsonConverter;\nimport com.alibaba.cloud.sentinel.datasource.converter.XmlConverter;\nimport com.alibaba.csp.sentinel.slots.block.RuleConstant;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRule;\nimport org.junit.jupiter.api.Test;\nimport tools.jackson.databind.ObjectMapper;\nimport tools.jackson.dataformat.xml.XmlMapper;\n\nimport org.springframework.util.ResourceUtils;\nimport org.springframework.util.StringUtils;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatExceptionOfType;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class SentinelConverterTests {\n\n\tprivate ObjectMapper objectMapper = new ObjectMapper();\n\n\tprivate XmlMapper xmlMapper = new XmlMapper();\n\n\t@Test\n\tpublic void testJsonConverter() {\n\t\tJsonConverter jsonConverter = new JsonConverter(objectMapper, FlowRule.class);\n\t\tList<FlowRule> flowRules = (List<FlowRule>) jsonConverter\n\t\t\t\t.convert(readFileContent(\"classpath: flowrule.json\"));\n\n\t\tassertThat(flowRules.size()).isEqualTo(1);\n\t\tassertThat(flowRules.get(0).getResource()).isEqualTo(\"resource\");\n\t\tassertThat(flowRules.get(0).getLimitApp()).isEqualTo(\"default\");\n\t\tassertThat(String.valueOf(flowRules.get(0).getCount())).isEqualTo(\"1.0\");\n\t\tassertThat(flowRules.get(0).getControlBehavior())\n\t\t\t\t.isEqualTo(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);\n\t\tassertThat(flowRules.get(0).getStrategy())\n\t\t\t\t.isEqualTo(RuleConstant.STRATEGY_DIRECT);\n\t\tassertThat(flowRules.get(0).getGrade()).isEqualTo(RuleConstant.FLOW_GRADE_QPS);\n\t}\n\n\t@Test\n\tpublic void testConverterEmptyContent() {\n\t\tJsonConverter jsonConverter = new JsonConverter(objectMapper, FlowRule.class);\n\t\tList<FlowRule> flowRules = (List<FlowRule>) jsonConverter.convert(\"\");\n\t\tassertThat(flowRules.size()).isEqualTo(0);\n\t}\n\n\t@Test\n\tpublic void testConverterErrorFormat() {\n\t\tassertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {\n\t\t\tJsonConverter jsonConverter = new JsonConverter(objectMapper, FlowRule.class);\n\t\t\tjsonConverter\n\t\t\t\t\t.convert(readFileContent(\"classpath: flowrule-errorformat.json\"));\n\t\t});\n\t}\n\n\t@Test\n\tpublic void testConverterErrorContent() {\n\t\t// see https://github.com/FasterXML/jackson-databind/issues/493\n\t\tassertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {\n\t\t\tJsonConverter jsonConverter = new JsonConverter(objectMapper, FlowRule.class);\n\t\t\tjsonConverter\n\t\t\t\t\t.convert(readFileContent(\"classpath: flowrule-errorcontent.json\"));\n\t\t});\n\t}\n\n\t@Test\n\tpublic void testXmlConverter() {\n\t\tXmlConverter jsonConverter = new XmlConverter(xmlMapper, FlowRule.class);\n\t\tList<FlowRule> flowRules = (List<FlowRule>) jsonConverter\n\t\t\t\t.convert(readFileContent(\"classpath: flowrule.xml\"));\n\n\t\tassertThat(flowRules.size()).isEqualTo(2);\n\t\tassertThat(flowRules.get(0).getResource()).isEqualTo(\"resource\");\n\t\tassertThat(flowRules.get(0).getLimitApp()).isEqualTo(\"default\");\n\t\tassertThat(String.valueOf(flowRules.get(0).getCount())).isEqualTo(\"1.0\");\n\t\tassertThat(flowRules.get(0).getControlBehavior())\n\t\t\t\t.isEqualTo(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);\n\t\tassertThat(flowRules.get(0).getStrategy())\n\t\t\t\t.isEqualTo(RuleConstant.STRATEGY_DIRECT);\n\t\tassertThat(flowRules.get(0).getGrade()).isEqualTo(RuleConstant.FLOW_GRADE_QPS);\n\n\t\tassertThat(flowRules.get(1).getResource()).isEqualTo(\"test\");\n\t\tassertThat(flowRules.get(1).getLimitApp()).isEqualTo(\"default\");\n\t\tassertThat(String.valueOf(flowRules.get(1).getCount())).isEqualTo(\"1.0\");\n\t\tassertThat(flowRules.get(1).getControlBehavior())\n\t\t\t\t.isEqualTo(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);\n\t\tassertThat(flowRules.get(1).getStrategy())\n\t\t\t\t.isEqualTo(RuleConstant.STRATEGY_DIRECT);\n\t\tassertThat(flowRules.get(1).getGrade()).isEqualTo(RuleConstant.FLOW_GRADE_QPS);\n\t}\n\n\tprivate String readFileContent(String file) {\n\t\ttry {\n\t\t\treturn FileUtils.readFileToString(\n\t\t\t\t\tResourceUtils.getFile(StringUtils.trimAllWhitespace(file)),\n\t\t\t\t\tCharset.defaultCharset());\n\t\t}\n\t\tcatch (IOException e) {\n\t\t\treturn \"\";\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/ZookeeperDataSourceFactoryBeanTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.datasource;\n\nimport com.alibaba.cloud.sentinel.datasource.converter.XmlConverter;\nimport com.alibaba.cloud.sentinel.datasource.factorybean.ZookeeperDataSourceFactoryBean;\nimport com.alibaba.csp.sentinel.datasource.Converter;\nimport com.alibaba.csp.sentinel.datasource.zookeeper.ZookeeperDataSource;\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.Mockito.doReturn;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.spy;\nimport static org.mockito.Mockito.when;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class ZookeeperDataSourceFactoryBeanTests {\n\n\tprivate String dataId = \"dataId\";\n\n\tprivate String groupId = \"groupId\";\n\n\tprivate String serverAddr = \"localhost:2181\";\n\n\tprivate String path = \"/sentinel\";\n\n\t@Test\n\tpublic void testZKWithoutPathFactoryBean() throws Exception {\n\t\tZookeeperDataSourceFactoryBean factoryBean = spy(\n\t\t\t\tZookeeperDataSourceFactoryBean.class);\n\n\t\tConverter converter = mock(XmlConverter.class);\n\n\t\tZookeeperDataSource zookeeperDataSource = mock(ZookeeperDataSource.class);\n\n\t\tfactoryBean.setConverter(converter);\n\t\tfactoryBean.setDataId(dataId);\n\t\tfactoryBean.setGroupId(groupId);\n\t\tfactoryBean.setServerAddr(serverAddr);\n\n\t\twhen(zookeeperDataSource.readSource()).thenReturn(\"{}\");\n\t\tdoReturn(zookeeperDataSource).when(factoryBean).getObject();\n\n\t\tassertThat(factoryBean.getObject()).isEqualTo(zookeeperDataSource);\n\t\tassertThat(factoryBean.getObject().readSource()).isEqualTo(\"{}\");\n\t\tassertThat(factoryBean.getDataId()).isEqualTo(dataId);\n\t\tassertThat(factoryBean.getConverter()).isEqualTo(converter);\n\t\tassertThat(factoryBean.getGroupId()).isEqualTo(groupId);\n\t\tassertThat(factoryBean.getServerAddr()).isEqualTo(serverAddr);\n\t}\n\n\t@Test\n\tpublic void testZKWithPathFactoryBean() throws Exception {\n\t\tZookeeperDataSourceFactoryBean factoryBean = spy(\n\t\t\t\tZookeeperDataSourceFactoryBean.class);\n\n\t\tConverter converter = mock(XmlConverter.class);\n\n\t\tZookeeperDataSource zookeeperDataSource = mock(ZookeeperDataSource.class);\n\n\t\tfactoryBean.setConverter(converter);\n\t\tfactoryBean.setPath(path);\n\t\tfactoryBean.setServerAddr(serverAddr);\n\n\t\twhen(zookeeperDataSource.readSource()).thenReturn(\"{}\");\n\t\tdoReturn(zookeeperDataSource).when(factoryBean).getObject();\n\n\t\tassertThat(factoryBean.getObject()).isEqualTo(zookeeperDataSource);\n\t\tassertThat(factoryBean.getObject().readSource()).isEqualTo(\"{}\");\n\t\tassertThat(factoryBean.getConverter()).isEqualTo(converter);\n\t\tassertThat(factoryBean.getPath()).isEqualTo(path);\n\t\tassertThat(factoryBean.getServerAddr()).isEqualTo(serverAddr);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/resources/flowrule-errorcontent.json",
    "content": "[\n  {\n    \"controlBehavior\": \"test\",\n    \"count\": 1,\n    \"grade\": 1,\n    \"limitApp\": \"default\",\n    \"strategy\": 0\n  }\n]\n\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/resources/flowrule-errorformat.json",
    "content": "[\n  {\n    \"resource\": \"resource\",\n    \"controlBehavior\": 0,\n    \"count\": 1,\n    \"grade\": 1,\n    \"limitApp\": \"default\",\n    \"strategy\": 0\n  }==\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/resources/flowrule.json",
    "content": "[\n  {\n    \"resource\": \"resource\",\n    \"controlBehavior\": 0,\n    \"count\": 1,\n    \"grade\": 1,\n    \"limitApp\": \"default\",\n    \"strategy\": 0\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/resources/flowrule.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<Rules>\n    <FlowRule>\n        <resource>resource</resource>\n        <controlBehavior>0</controlBehavior>\n        <count>1</count>\n        <grade>1</grade>\n        <limitApp>default</limitApp>\n        <strategy>0</strategy>\n    </FlowRule>\n    <FlowRule>\n        <resource>test</resource>\n        <controlBehavior>0</controlBehavior>\n        <count>1</count>\n        <grade>1</grade>\n        <limitApp>default</limitApp>\n        <strategy>0</strategy>\n    </FlowRule>\n</Rules>\n\n\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/README.md",
    "content": "# Sentinel Spring Cloud Zuul Adapter\n\nZuul does not provide rateLimit function, If you use default `SentinelRibbonFilter` route filter. it wrapped by Hystrix Command. so only provide Service level \ncircuit protection. \n\nSentinel can provide `ServiceId` level and `API Path` level flow control for spring cloud zuul gateway service. \n\n*Note*: this project is for zuul 1.\n\n## How to use\n\n1. Add maven dependency\n\n```xml\n<dependency>\n    <groupId>com.alibaba.cloud</groupId>\n    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>\n    <version>x.y.z</version>\n</dependency>\n\n```\n\n2. Set application.property\n\n```\n// default value is false\nspring.cloud.sentinel.zuul.enabled=true\n```\n\n## How it works\n\nAs Zuul run as per thread connection block model, we add filters around `route Filter` to trace sentinel statistics.   \n\n- `SentinelPreFilter`: Get an entry of resource,the first order is **ServiceId**, then **API Path**. \n- `SentinelPostFilter`: When success response,exit entry.\n- `SentinelErrorFilter`:  When get an `Exception`, trace the exception and exit context. \n\n\nthe order of Filter can be changed by configuration:\n\n```\nspring.cloud.sentinel.zuul.order.post=0\nspring.cloud.sentinel.zuul.order.pre=10000\nspring.cloud.sentinel.zuul.order.error=-1\n```\n\n\nFilters create structure like:\n\n\n```bash\n\nEntranceNode: machine-root(t:3 pq:0 bq:0 tq:0 rt:0 prq:0 1mp:0 1mb:0 1mt:0)\n-EntranceNode: coke(t:2 pq:0 bq:0 tq:0 rt:0 prq:0 1mp:0 1mb:0 1mt:0)\n--coke(t:2 pq:0 bq:0 tq:0 rt:0 prq:0 1mp:0 1mb:0 1mt:0)\n---/coke/uri(t:0 pq:0 bq:0 tq:0 rt:0 prq:0 1mp:0 1mb:0 1mt:0)\n-EntranceNode: sentinel_default_context(t:0 pq:0 bq:0 tq:0 rt:0 prq:0 1mp:0 1mb:0 1mt:0)\n-EntranceNode: book(t:1 pq:0 bq:0 tq:0 rt:0 prq:0 1mp:0 1mb:0 1mt:0)\n--book(t:1 pq:0 bq:0 tq:0 rt:0 prq:0 1mp:0 1mb:0 1mt:0)\n---/book/uri(t:0 pq:0 bq:0 tq:0 rt:0 prq:0 1mp:0 1mb:0 1mt:0)\n\n```\n\n`book` and `coke` are serviceId. \n\n`---/book/uri` is api path, the real uri is `/uri`. \n\n\n## Integration with Sentinel DashBord\n\nStart [Sentinel DashBord](https://github.com/alibaba/Sentinel/wiki/%E6%8E%A7%E5%88%B6%E5%8F%B0).\n\n## Rule config with dataSource\n\nSentinel has full rule config features. see [Dynamic-Rule-Configuration](https://github.com/alibaba/Sentinel/wiki/Dynamic-Rule-Configuration)\n\n\n## Custom Fallbacks\n\nImplements `SentinelFallbackProvider` to define your own Fallback Provider when Sentinel Block Exception throwing for different rout. the default \nFallback Provider is `DefaultBlockFallbackProvider`. \n\nBy default, fallback route is `ServiveId + URI PATH`, example `/book/coke`, first `book` is serviceId, `/uri` is URI PATH, so both  \ncan be needed.\n\nHere is an example:\n\n```java\n\n// custom provider \npublic class MyCokeServiceBlockFallbackProvider implements SentinelFallbackProvider {\n\n    private Logger logger = LoggerFactory.getLogger(DefaultBlockFallbackProvider.class);\n    \n    // you can define root as service level \n    @Override\n    public String getRoute() {\n        return \"/coke/uri\";\n    }\n\n    @Override\n    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {\n        if (cause instanceof BlockException) {\n            logger.info(\"get in fallback block exception:{}\", cause);\n            return response(HttpStatus.TOO_MANY_REQUESTS, route);\n        } else {\n            return response(HttpStatus.INTERNAL_SERVER_ERROR, route);\n        }\n    }\n }\n\n```\n\n## Custom Request Origin Parser\nBy default, this adapter use `DefaultRequestOriginParser` to parse sentinel origin.\n\n```java\n\npublic class CustomRequestOriginParser implements RequestOriginParser {\n    @Override\n    public String parseOrigin(HttpServletRequest request) {\n        // do custom logic.\n        return \"\";\n    }\n}\n\n```\n\n## Custom UrlCleaner\nBy default this adapter use `DefaultUrlCleaner` to define uri resource. \n\n```java\npublic class CustomUrlCleaner implements UrlCleaner {\n\n    @Override\n    public String clean(String originUrl) {\n        // do custom logic.\n        return originUrl;\n    }\n}\n```\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-starters</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>\n    <name>Spring Cloud Alibaba Sentinel Gateway</name>\n\n    <dependencies>\n\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-configuration-processor</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-api-gateway-adapter-common</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-parameter-flow-control</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-spring-cloud-gateway-v6x-adapter</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-gateway-server-webflux</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>tools.jackson.dataformat</groupId>\n            <artifactId>jackson-dataformat-xml</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-datasource-extension</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>junit</groupId>\n            <artifactId>junit</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n</project>"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/ConfigConstants.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.gateway;\n\nimport com.alibaba.cloud.sentinel.gateway.scg.SentinelGatewayProperties;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic final class ConfigConstants {\n\n\t/**\n\t * Spring Cloud Gateway type.\n\t */\n\tpublic static final String APP_TYPE_SCG_GATEWAY = \"11\";\n\n\t/**\n\t * ConfigurationProperties for {@link SentinelGatewayProperties}.\n\t */\n\tpublic static final String GATEWAY_PREFIX = \"spring.cloud.sentinel.scg\";\n\n\t/**\n\t * Response type for Spring Cloud Gateway fallback.\n\t */\n\tpublic static final String FALLBACK_MSG_RESPONSE = \"response\";\n\n\t/**\n\t * Redirect type for Spring Cloud Gateway fallback.\n\t */\n\tpublic static final String FALLBACK_REDIRECT = \"redirect\";\n\n\tprivate ConfigConstants() {\n\t\tthrow new AssertionError(\"Must not instantiate constant utility class\");\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/FallbackProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.gateway;\n\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class FallbackProperties {\n\n\t/**\n\t * The fallback mode for sentinel spring-cloud-gateway. choose `redirect` or\n\t * `response`.\n\t */\n\tprivate String mode;\n\n\t/**\n\t * Redirect Url for `redirect` mode.\n\t */\n\tprivate String redirect;\n\n\t/**\n\t * Response Body for `response` mode.\n\t */\n\tprivate String responseBody;\n\n\t/**\n\t * Response Status for `response` mode.\n\t */\n\tprivate Integer responseStatus = HttpStatus.TOO_MANY_REQUESTS.value();\n\n\t/**\n\t * Content-Type for `response` mode.\n\t */\n\tprivate String contentType = MediaType.APPLICATION_JSON.toString();\n\n\tpublic String getMode() {\n\t\treturn mode;\n\t}\n\n\tpublic FallbackProperties setMode(String mode) {\n\t\tthis.mode = mode;\n\t\treturn this;\n\t}\n\n\tpublic String getRedirect() {\n\t\treturn redirect;\n\t}\n\n\tpublic FallbackProperties setRedirect(String redirect) {\n\t\tthis.redirect = redirect;\n\t\treturn this;\n\t}\n\n\tpublic String getResponseBody() {\n\t\treturn responseBody;\n\t}\n\n\tpublic FallbackProperties setResponseBody(String responseBody) {\n\t\tthis.responseBody = responseBody;\n\t\treturn this;\n\t}\n\n\tpublic Integer getResponseStatus() {\n\t\treturn responseStatus;\n\t}\n\n\tpublic FallbackProperties setResponseStatus(Integer responseStatus) {\n\t\tthis.responseStatus = responseStatus;\n\t\treturn this;\n\t}\n\n\tpublic String getContentType() {\n\t\treturn contentType;\n\t}\n\n\tpublic FallbackProperties setContentType(String contentType) {\n\t\tthis.contentType = contentType;\n\t\treturn this;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/GatewayEnvironmentPostProcessor.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.gateway;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport org.springframework.boot.EnvironmentPostProcessor;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.core.env.ConfigurableEnvironment;\nimport org.springframework.core.env.MapPropertySource;\nimport org.springframework.core.env.MutablePropertySources;\nimport org.springframework.core.env.PropertySource;\n\n/**\n * @author zhuhonghan\n */\npublic class GatewayEnvironmentPostProcessor implements EnvironmentPostProcessor {\n\n\tprivate final static String SENTINEL_FILTER_ENABLED = \"spring.cloud.sentinel.filter.enabled\";\n\n\tprivate final static String PROPERTY_SOURCE_NAME = \"defaultProperties\";\n\n\t@Override\n\tpublic void postProcessEnvironment(ConfigurableEnvironment environment,\n\t\t\tSpringApplication springApplication) {\n\t\taddDefaultPropertySource(environment);\n\t}\n\n\tprivate void addDefaultPropertySource(ConfigurableEnvironment environment) {\n\n\t\tMap<String, Object> map = new HashMap<String, Object>();\n\n\t\tconfigureDefaultProperties(map);\n\n\t\taddOrReplace(environment.getPropertySources(), map);\n\t}\n\n\tprivate void configureDefaultProperties(Map<String, Object> source) {\n\t\t// Required Properties\n\t\tsource.put(SENTINEL_FILTER_ENABLED, \"false\");\n\t}\n\n\tprivate void addOrReplace(MutablePropertySources propertySources,\n\t\t\tMap<String, Object> map) {\n\t\tMapPropertySource target = null;\n\t\tif (propertySources.contains(PROPERTY_SOURCE_NAME)) {\n\t\t\tPropertySource<?> source = propertySources.get(PROPERTY_SOURCE_NAME);\n\t\t\tif (source instanceof MapPropertySource mapPropertySource) {\n\t\t\t\ttarget = mapPropertySource;\n\t\t\t\tfor (String key : map.keySet()) {\n\t\t\t\t\tif (!target.containsProperty(key)) {\n\t\t\t\t\t\ttarget.getSource().put(key, map.get(key));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (target == null) {\n\t\t\ttarget = new MapPropertySource(PROPERTY_SOURCE_NAME, map);\n\t\t}\n\t\tif (!propertySources.contains(PROPERTY_SOURCE_NAME)) {\n\t\t\tpropertySources.addLast(target);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/SentinelGatewayAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.gateway;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport com.alibaba.cloud.sentinel.datasource.converter.JsonConverter;\nimport com.alibaba.cloud.sentinel.datasource.converter.XmlConverter;\nimport com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;\nimport com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;\nimport com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateGroupItem;\nimport com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;\nimport com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;\nimport tools.jackson.core.JsonParser;\nimport tools.jackson.core.Version;\nimport tools.jackson.databind.DeserializationContext;\nimport tools.jackson.databind.DeserializationFeature;\nimport tools.jackson.databind.JsonNode;\nimport tools.jackson.databind.ObjectMapper;\nimport tools.jackson.databind.deser.std.StdDeserializer;\nimport tools.jackson.databind.json.JsonMapper;\nimport tools.jackson.databind.module.SimpleModule;\nimport tools.jackson.dataformat.xml.XmlMapper;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnProperty(name = \"spring.cloud.sentinel.enabled\", matchIfMissing = true)\npublic class SentinelGatewayAutoConfiguration {\n\n\t@ConditionalOnClass(ObjectMapper.class)\n\t@Configuration(proxyBeanMethods = false)\n\tprotected static class SentinelConverterConfiguration {\n\n\t\tstatic class ApiPredicateItemDeserializer\n\t\t\t\textends StdDeserializer<ApiPredicateItem> {\n\n\t\t\tprivate Map<String, Class<? extends ApiPredicateItem>> registry = new HashMap<String, Class<? extends ApiPredicateItem>>();\n\n\t\t\tApiPredicateItemDeserializer() {\n\t\t\t\tsuper(ApiPredicateItem.class);\n\t\t\t}\n\n\t\t\tvoid registerApiPredicateItem(String uniqueAttribute,\n\t\t\t\t\tClass<? extends ApiPredicateItem> apiPredicateItemClass) {\n\t\t\t\tregistry.put(uniqueAttribute, apiPredicateItemClass);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic ApiPredicateItem deserialize(JsonParser jp,\n\t\t\t\t\tDeserializationContext ctxt) {\n\t\t\t\tJsonNode root = ctxt.readTree(jp);\n\t\t\t\tClass<? extends ApiPredicateItem> apiPredicateItemClass = null;\n\t\t\t\tfor (String name : root.propertyNames()) {\n\t\t\t\t\tif (registry.containsKey(name)) {\n\t\t\t\t\t\tapiPredicateItemClass = registry.get(name);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (apiPredicateItemClass == null) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\treturn ctxt.readTreeAsValue(root, apiPredicateItemClass);\n\t\t\t}\n\n\t\t}\n\n\t\t@Configuration(proxyBeanMethods = false)\n\t\tprotected static class SentinelJsonConfiguration {\n\n\t\t\tprivate final ObjectMapper objectMapper;\n\n\t\t\tpublic SentinelJsonConfiguration() {\n\t\t\t\tApiPredicateItemDeserializer deserializer = new ApiPredicateItemDeserializer();\n\t\t\t\tdeserializer.registerApiPredicateItem(\"pattern\",\n\t\t\t\t\t\tApiPathPredicateItem.class);\n\t\t\t\tdeserializer.registerApiPredicateItem(\"items\",\n\t\t\t\t\t\tApiPredicateGroupItem.class);\n\t\t\t\tSimpleModule module = new SimpleModule(\n\t\t\t\t\t\t\"PolymorphicApiPredicateItemDeserializerModule\",\n\t\t\t\t\t\tnew Version(1, 0, 0, null, null, null));\n\t\t\t\tmodule.addDeserializer(ApiPredicateItem.class, deserializer);\n\n\t\t\t\tthis.objectMapper = JsonMapper.builder()\n\t\t\t\t\t\t.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)\n\t\t\t\t\t\t.addModule(module)\n\t\t\t\t\t\t.build();\n\t\t\t}\n\n\t\t\t@Bean(\"sentinel-json-gw-flow-converter\")\n\t\t\tpublic JsonConverter jsonGatewayFlowConverter() {\n\t\t\t\treturn new JsonConverter(objectMapper, GatewayFlowRule.class);\n\t\t\t}\n\n\t\t\t@Bean(\"sentinel-json-gw-api-group-converter\")\n\t\t\tpublic JsonConverter jsonApiConverter() {\n\t\t\t\treturn new JsonConverter(objectMapper, ApiDefinition.class);\n\t\t\t}\n\n\t\t}\n\n\t\t@ConditionalOnClass(XmlMapper.class)\n\t\t@Configuration(proxyBeanMethods = false)\n\t\tprotected static class SentinelXmlConfiguration {\n\n\t\t\tprivate final XmlMapper xmlMapper;\n\n\t\t\tpublic SentinelXmlConfiguration() {\n\t\t\t\tApiPredicateItemDeserializer deserializer = new ApiPredicateItemDeserializer();\n\t\t\t\tdeserializer.registerApiPredicateItem(\"pattern\",\n\t\t\t\t\t\tApiPathPredicateItem.class);\n\t\t\t\tdeserializer.registerApiPredicateItem(\"items\",\n\t\t\t\t\t\tApiPredicateGroupItem.class);\n\t\t\t\tSimpleModule module = new SimpleModule(\n\t\t\t\t\t\t\"PolymorphicGatewayDeserializerModule\",\n\t\t\t\t\t\tnew Version(1, 0, 0, null, null, null));\n\t\t\t\tmodule.addDeserializer(ApiPredicateItem.class, deserializer);\n\n\t\t\t\tthis.xmlMapper = XmlMapper.builder()\n\t\t\t\t\t\t.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)\n\t\t\t\t\t\t.addModule(module)\n\t\t\t\t\t\t.build();\n\t\t\t}\n\n\t\t\t@Bean(\"sentinel-xml-gw-flow-converter\")\n\t\t\tpublic XmlConverter xmlGatewayFlowConverter() {\n\t\t\t\treturn new XmlConverter(xmlMapper, GatewayFlowRule.class);\n\t\t\t}\n\n\t\t\t@Bean(\"sentinel-xml-gw-api-group-converter\")\n\t\t\tpublic XmlConverter xmlApiConverter() {\n\t\t\t\treturn new XmlConverter(xmlMapper, ApiDefinition.class);\n\t\t\t}\n\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/scg/SentinelGatewayProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.gateway.scg;\n\nimport com.alibaba.cloud.sentinel.gateway.ConfigConstants;\nimport com.alibaba.cloud.sentinel.gateway.FallbackProperties;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.boot.context.properties.NestedConfigurationProperty;\nimport org.springframework.core.Ordered;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@ConfigurationProperties(prefix = ConfigConstants.GATEWAY_PREFIX)\npublic class SentinelGatewayProperties {\n\n\t@NestedConfigurationProperty\n\tprivate FallbackProperties fallback;\n\n\tprivate Integer order = Ordered.HIGHEST_PRECEDENCE;\n\n\tpublic FallbackProperties getFallback() {\n\t\treturn fallback;\n\t}\n\n\tpublic SentinelGatewayProperties setFallback(FallbackProperties fallback) {\n\t\tthis.fallback = fallback;\n\t\treturn this;\n\t}\n\n\tpublic Integer getOrder() {\n\t\treturn order;\n\t}\n\n\tpublic void setOrder(Integer order) {\n\t\tthis.order = order;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/scg/SentinelSCGAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.gateway.scg;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Optional;\n\nimport com.alibaba.cloud.sentinel.gateway.ConfigConstants;\nimport com.alibaba.cloud.sentinel.gateway.FallbackProperties;\nimport com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;\nimport com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;\nimport com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;\nimport com.alibaba.csp.sentinel.adapter.gateway.sc.callback.RedirectBlockRequestHandler;\nimport com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;\nimport com.alibaba.csp.sentinel.config.SentinelConfig;\nimport com.alibaba.csp.sentinel.util.StringUtil;\nimport jakarta.annotation.PostConstruct;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.ObjectProvider;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.cloud.gateway.filter.GlobalFilter;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.Ordered;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.codec.ServerCodecConfigurer;\nimport org.springframework.web.reactive.function.server.ServerResponse;\nimport org.springframework.web.reactive.result.view.ViewResolver;\n\nimport static org.springframework.web.reactive.function.BodyInserters.fromValue;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnClass(GlobalFilter.class)\n@ConditionalOnProperty(prefix = ConfigConstants.GATEWAY_PREFIX, name = \"enabled\",\n\t\thavingValue = \"true\", matchIfMissing = true)\n@EnableConfigurationProperties(SentinelGatewayProperties.class)\npublic class SentinelSCGAutoConfiguration {\n\n\tprivate static final Logger logger = LoggerFactory\n\t\t\t.getLogger(SentinelSCGAutoConfiguration.class);\n\n\tprivate final List<ViewResolver> viewResolvers;\n\n\tprivate final ServerCodecConfigurer serverCodecConfigurer;\n\n\t@Autowired\n\tprivate Optional<BlockRequestHandler> blockRequestHandlerOptional;\n\n\t@Autowired\n\tprivate SentinelGatewayProperties gatewayProperties;\n\n\t@PostConstruct\n\tpublic void init() {\n\t\t// blockRequestHandlerOptional has low priority\n\t\tblockRequestHandlerOptional.ifPresent(GatewayCallbackManager::setBlockHandler);\n\t\tinitAppType();\n\t\tinitFallback();\n\t}\n\n\tpublic SentinelSCGAutoConfiguration(\n\t\t\tObjectProvider<List<ViewResolver>> viewResolversProvider,\n\t\t\tServerCodecConfigurer serverCodecConfigurer) {\n\t\tthis.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);\n\t\tthis.serverCodecConfigurer = serverCodecConfigurer;\n\t}\n\n\tprivate void initAppType() {\n\t\tSystem.setProperty(SentinelConfig.APP_TYPE_PROP_KEY,\n\t\t\t\tConfigConstants.APP_TYPE_SCG_GATEWAY);\n\t}\n\n\tprivate void initFallback() {\n\t\tFallbackProperties fallbackProperties = gatewayProperties.getFallback();\n\t\tif (fallbackProperties == null\n\t\t\t\t|| StringUtil.isBlank(fallbackProperties.getMode())) {\n\t\t\treturn;\n\t\t}\n\t\tif (ConfigConstants.FALLBACK_MSG_RESPONSE.equals(fallbackProperties.getMode())) {\n\t\t\tif (StringUtil.isNotBlank(fallbackProperties.getResponseBody())) {\n\t\t\t\tGatewayCallbackManager.setBlockHandler((exchange, t) -> ServerResponse\n\t\t\t\t\t\t.status(fallbackProperties.getResponseStatus())\n\t\t\t\t\t\t.contentType(\n\t\t\t\t\t\t\t\tMediaType.valueOf(fallbackProperties.getContentType()))\n\t\t\t\t\t\t.body(fromValue(fallbackProperties.getResponseBody())));\n\t\t\t\tlogger.info(\n\t\t\t\t\t\t\"[Sentinel SpringCloudGateway] using AnonymousBlockRequestHandler, responseStatus: \"\n\t\t\t\t\t\t\t\t+ fallbackProperties.getResponseStatus()\n\t\t\t\t\t\t\t\t+ \", responseBody: \"\n\t\t\t\t\t\t\t\t+ fallbackProperties.getResponseBody());\n\t\t\t}\n\t\t}\n\t\tString redirectUrl = fallbackProperties.getRedirect();\n\t\tif (ConfigConstants.FALLBACK_REDIRECT.equals(fallbackProperties.getMode())\n\t\t\t\t&& StringUtil.isNotBlank(redirectUrl)) {\n\t\t\tGatewayCallbackManager\n\t\t\t\t\t.setBlockHandler(new RedirectBlockRequestHandler(redirectUrl));\n\t\t\tlogger.info(\n\t\t\t\t\t\"[Sentinel SpringCloudGateway] using RedirectBlockRequestHandler, redirectUrl: \"\n\t\t\t\t\t\t\t+ redirectUrl);\n\t\t}\n\t}\n\n\t@Bean\n\t@Order(Ordered.HIGHEST_PRECEDENCE)\n\t@ConditionalOnMissingBean\n\tpublic SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {\n\t\t// Register the block exception handler for Spring Cloud Gateway.\n\t\tlogger.info(\n\t\t\t\t\"[Sentinel SpringCloudGateway] register SentinelGatewayBlockExceptionHandler\");\n\t\treturn new SentinelGatewayBlockExceptionHandler(viewResolvers,\n\t\t\t\tserverCodecConfigurer);\n\t}\n\n\t@Bean\n\t@Order(-1)\n\t@ConditionalOnMissingBean\n\tpublic SentinelGatewayFilter sentinelGatewayFilter() {\n\t\tlogger.info(\n\t\t\t\t\"[Sentinel SpringCloudGateway] register SentinelGatewayFilter with order: {}\",\n\t\t\t\tgatewayProperties.getOrder());\n\t\treturn new SentinelGatewayFilter(gatewayProperties.getOrder());\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports",
    "content": "com.alibaba.cloud.sentinel.gateway.scg.SentinelSCGAutoConfiguration\ncom.alibaba.cloud.sentinel.gateway.SentinelGatewayAutoConfiguration\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/resources/META-INF/spring.factories",
    "content": "org.springframework.boot.EnvironmentPostProcessor=com.alibaba.cloud.sentinel.gateway.GatewayEnvironmentPostProcessor\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/ConfigConstantsTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.gateway;\n\nimport junit.framework.Assert;\nimport org.junit.Test;\n\npublic class ConfigConstantsTest {\n\t@Test\n\tpublic void testConfigConstants() {\n\t\tAssert.assertEquals(\"11\", ConfigConstants.APP_TYPE_SCG_GATEWAY);\n\t\tAssert.assertEquals(\"spring.cloud.sentinel.scg\", ConfigConstants.GATEWAY_PREFIX);\n\t\tAssert.assertEquals(\"response\", ConfigConstants.FALLBACK_MSG_RESPONSE);\n\t\tAssert.assertEquals(\"redirect\", ConfigConstants.FALLBACK_REDIRECT);\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/FallbackPropertiesTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.gateway;\n\nimport junit.framework.Assert;\nimport org.junit.Test;\n\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\n\npublic class FallbackPropertiesTest {\n\n\t/**\n\t * Tests the correct setting and retrieval of fallback properties.\n\t * This test case verifies that the FallbackProperties class correctly sets and retrieves\n\t * various properties for fallback responses, including the response mode, redirect URL,\n\t * response body content, HTTP status code, and content type.\n\t */\n\t@Test\n\tpublic void testFallbackProperties() {\n\t\tFallbackProperties properties = new FallbackProperties()\n\t\t\t\t.setMode(\"response\")\n\t\t\t\t.setRedirect(\"http://example.com\")\n\t\t\t\t.setResponseBody(\"{'message': 'Fallback response'}\")\n\t\t\t\t.setResponseStatus(HttpStatus.TOO_EARLY.value())\n\t\t\t\t.setContentType(\"application/json\");\n\n\t\tAssert.assertEquals(\"response\", properties.getMode());\n\t\tAssert.assertEquals(\"http://example.com\", properties.getRedirect());\n\t\tAssert.assertEquals(\"{'message': 'Fallback response'}\", properties.getResponseBody());\n\t\tAssert.assertEquals(HttpStatus.TOO_EARLY.value(), properties.getResponseStatus().intValue());\n\t\tAssert.assertEquals(\"application/json\", properties.getContentType());\n\t}\n\n\t/**\n\t * This test method checks the default values of a FallbackProperties object.\n\t * It verifies that certain properties are not set (null) and others have default values.\n\t */\n\t@Test\n\tpublic void testDefaultValues() {\n\t\tFallbackProperties properties = new FallbackProperties();\n\t\tAssert.assertNull(properties.getMode());\n\t\tAssert.assertNull(properties.getRedirect());\n\t\tAssert.assertNull(properties.getResponseBody());\n\t\tAssert.assertEquals(HttpStatus.TOO_MANY_REQUESTS.value(), properties.getResponseStatus().intValue());\n\t\tAssert.assertEquals(MediaType.APPLICATION_JSON.toString(), properties.getContentType());\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/GatewayEnvironmentPostProcessorTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.gateway;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport junit.framework.Assert;\nimport org.junit.Test;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.core.env.ConfigurableEnvironment;\nimport org.springframework.core.env.MapPropertySource;\nimport org.springframework.core.env.MutablePropertySources;\nimport org.springframework.core.env.PropertySource;\n\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\npublic class GatewayEnvironmentPostProcessorTest {\n\t/**\n\t * Tests the custom property source processing logic.\n\t * This test case verifies whether the custom property source is correctly added during the environment post-processing.\n\t * Specifically, it checks if the configuration property \"spring.cloud.sentinel.filter.enabled\" is properly added.\n\t */\n\t@Test\n\tpublic void testPostProcessEnvironment() {\n\t\tConfigurableEnvironment environment = mock(ConfigurableEnvironment.class);\n\t\tMutablePropertySources propertySources = new MutablePropertySources();\n\t\twhen(environment.getPropertySources()).thenReturn(propertySources);\n\n\t\tGatewayEnvironmentPostProcessor postProcessor = new GatewayEnvironmentPostProcessor();\n\t\tpostProcessor.postProcessEnvironment(environment, mock(SpringApplication.class));\n\n\t\tPropertySource<?> propertySource = propertySources.get(\"defaultProperties\");\n\t\tAssert.assertNotNull(propertySource);\n\t\tAssert.assertNotNull(propertySource.getProperty(\"spring.cloud.sentinel.filter.enabled\"));\n\t}\n\n\t/**\n\t * Tests the logic of processing an environment that already contains a property source.\n\t * This test case simulates an environment with an existing property source and checks if the post-processor can interact correctly with these property sources.\n\t */\n\t@Test\n\tpublic void testPostProcessEnvironmentWithExistingPropertySource() {\n\t\tConfigurableEnvironment environment = mock(ConfigurableEnvironment.class);\n\t\tMutablePropertySources propertySources = new MutablePropertySources();\n\t\twhen(environment.getPropertySources()).thenReturn(propertySources);\n\n\t\tMap<String, Object> existingProperties = new HashMap<>();\n\t\texistingProperties.put(\"existing.property\", \"value\");\n\t\tMapPropertySource existingPropertySource = new MapPropertySource(\"defaultProperties\", existingProperties);\n\t\tpropertySources.addFirst(existingPropertySource);\n\n\t\tGatewayEnvironmentPostProcessor postProcessor = new GatewayEnvironmentPostProcessor();\n\t\tpostProcessor.postProcessEnvironment(environment, mock(SpringApplication.class));\n\n\t\tPropertySource<?> propertySource = propertySources.get(\"defaultProperties\");\n\t\tAssert.assertNotNull(propertySource);\n\t\tAssert.assertEquals(\"value\", propertySource.getProperty(\"existing.property\"));\n\t\tAssert.assertEquals(\"false\", propertySource.getProperty(\"spring.cloud.sentinel.filter.enabled\"));\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/SentinelGatewayAutoConfigurationTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.gateway;\n\nimport java.io.IOException;\nimport java.nio.charset.Charset;\nimport java.util.ArrayList;\nimport java.util.Collection;\n\nimport com.alibaba.cloud.commons.io.FileUtils;\nimport com.alibaba.cloud.sentinel.datasource.converter.JsonConverter;\nimport com.alibaba.cloud.sentinel.datasource.converter.XmlConverter;\nimport com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;\nimport com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;\nimport junit.framework.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport org.springframework.util.ResourceUtils;\nimport org.springframework.util.StringUtils;\n\npublic class SentinelGatewayAutoConfigurationTest {\n\n\tprivate SentinelGatewayAutoConfiguration.SentinelConverterConfiguration.SentinelJsonConfiguration json;\n\tprivate SentinelGatewayAutoConfiguration.SentinelConverterConfiguration.SentinelXmlConfiguration xml;\n\n\t/**\n\t * Setup method to initialize test configurations.\n\t */\n\t@Before\n\tpublic void setup() {\n\t\tjson = new SentinelGatewayAutoConfiguration.SentinelConverterConfiguration.SentinelJsonConfiguration();\n\t\txml = new SentinelGatewayAutoConfiguration.SentinelConverterConfiguration.SentinelXmlConfiguration();\n\t}\n\n\t/**\n\t * Tests the JSON gateway flow rule converter.\n\t * Reads JSON content from a file, converts it to GatewayFlowRule collection, and validates the result.\n\t */\n\t@Test\n\tpublic void testJsonGatewayFlowConverter() {\n\t\tJsonConverter jsonGatewayFlowConverter = json.jsonGatewayFlowConverter();\n\t\tCollection<GatewayFlowRule> gatewayFlowRules = jsonGatewayFlowConverter.convert(readFileContent(\"classpath: gatewayflowrule.json\"));\n\t\tAssert.assertEquals(1, gatewayFlowRules.size());\n\t\tAssert.assertEquals(\"test\", new ArrayList<>(gatewayFlowRules).get(0).getResource());\n\t}\n\n\t/**\n\t * Tests the JSON API definition converter.\n\t * Reads JSON content from a file, converts it to ApiDefinition collection, and validates the result.\n\t */\n\t@Test\n\tpublic void testJsonApiConverter() {\n\t\tJsonConverter jsonApiConverter = json.jsonApiConverter();\n\t\tCollection<ApiDefinition> apiDefinitions = jsonApiConverter.convert(readFileContent(\"classpath: apidefinition.json\"));\n\t\tAssert.assertEquals(1, apiDefinitions.size());\n\t\tAssert.assertEquals(\"test\", new ArrayList<>(apiDefinitions).get(0).getApiName());\n\t}\n\n\t/**\n\t * Tests the XML gateway flow rule converter.\n\t * Reads XML content from a file, converts it to GatewayFlowRule collection, and validates the result.\n\t */\n\t@Test\n\tpublic void testXmlGatewayFlowConverter() {\n\t\tXmlConverter xmlGatewayFlowConverter = xml.xmlGatewayFlowConverter();\n\t\tCollection<GatewayFlowRule> gatewayFlowRules = xmlGatewayFlowConverter.convert(readFileContent(\"classpath: gatewayflowrule.xml\"));\n\t\tAssert.assertEquals(1, gatewayFlowRules.size());\n\t\tAssert.assertEquals(\"test\", new ArrayList<>(gatewayFlowRules).get(0).getResource());\n\t}\n\n\t/**\n\t * Tests the XML API definition converter.\n\t * Reads XML content from a file, converts it to ApiDefinition collection, and validates the result.\n\t */\n\t@Test\n\tpublic void testSentinelXmlConfiguration() {\n\t\tXmlConverter xmlApiConverter = xml.xmlApiConverter();\n\t\tCollection<ApiDefinition> apiDefinitions = xmlApiConverter.convert(readFileContent(\"classpath: apidefinition.xml\"));\n\t\tAssert.assertEquals(1, apiDefinitions.size());\n\t\tAssert.assertEquals(\"test\", new ArrayList<>(apiDefinitions).get(0).getApiName());\n\t}\n\n\t/**\n\t * Reads the content of a file.\n\t *\n\t * @param file the classpath location of the file\n\t * @return the content of the file as a string\n\t */\n\tprivate String readFileContent(String file) {\n\t\ttry {\n\t\t\treturn FileUtils.readFileToString(\n\t\t\t\t\tResourceUtils.getFile(StringUtils.trimAllWhitespace(file)),\n\t\t\t\t\tCharset.defaultCharset());\n\t\t}\n\t\tcatch (IOException e) {\n\t\t\treturn \"\";\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/scg/SentinelGatewayPropertiesTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.gateway.scg;\n\nimport com.alibaba.cloud.sentinel.gateway.FallbackProperties;\nimport junit.framework.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport org.springframework.core.Ordered;\n\npublic class SentinelGatewayPropertiesTest {\n\n\tprivate SentinelGatewayProperties properties;\n\n\t@Before\n\tpublic void setUp() {\n\t\tproperties = new SentinelGatewayProperties();\n\t}\n\n\t@Test\n\tpublic void testDefaultOrder() {\n\t\tAssert.assertEquals(Ordered.HIGHEST_PRECEDENCE, properties.getOrder().intValue());\n\t}\n\n\t@Test\n\tpublic void testSetOrder() {\n\t\tint newOrder = 100;\n\t\tproperties.setOrder(newOrder);\n\t\tAssert.assertEquals(newOrder, properties.getOrder().intValue());\n\t}\n\n\t@Test\n\tpublic void testFallbackPropertiesInitialization() {\n\t\tAssert.assertNull(properties.getFallback());\n\t}\n\n\t@Test\n\tpublic void testSetFallbackProperties() {\n\t\tFallbackProperties newFallback = new FallbackProperties();\n\t\tproperties.setFallback(newFallback);\n\t\tAssert.assertSame(newFallback, properties.getFallback());\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/scg/SentinelSCGAutoConfigurationTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.gateway.scg;\n\nimport java.lang.reflect.Field;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Optional;\n\nimport com.alibaba.cloud.sentinel.gateway.ConfigConstants;\nimport com.alibaba.cloud.sentinel.gateway.FallbackProperties;\nimport com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;\nimport junit.framework.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.mockito.Mock;\nimport org.mockito.MockitoAnnotations;\nimport reactor.core.publisher.Mono;\n\nimport org.springframework.beans.factory.ObjectProvider;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.codec.ServerCodecConfigurer;\nimport org.springframework.web.reactive.function.server.ServerResponse;\nimport org.springframework.web.reactive.result.view.ViewResolver;\nimport org.springframework.web.server.ServerWebExchange;\n\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\npublic class SentinelSCGAutoConfigurationTest {\n\n\t@Mock\n\tprivate ObjectProvider<List<ViewResolver>> viewResolversProvider;\n\n\t@Mock\n\tprivate ServerCodecConfigurer serverCodecConfigurer;\n\n\t@Mock\n\tprivate SentinelGatewayProperties gatewayProperties;\n\n\tprivate SentinelSCGAutoConfiguration config;\n\n\t@Before\n\tpublic void setup() throws Exception {\n\t\tMockitoAnnotations.openMocks(this).close();\n\t\tconfig = new SentinelSCGAutoConfiguration(viewResolversProvider, serverCodecConfigurer);\n\t\tField optional = SentinelSCGAutoConfiguration.class.getDeclaredField(\"blockRequestHandlerOptional\");\n\t\toptional.setAccessible(true);\n\t\toptional.set(config, Optional.empty());\n\t\tField properties = SentinelSCGAutoConfiguration.class.getDeclaredField(\"gatewayProperties\");\n\t\tproperties.setAccessible(true);\n\t\tproperties.set(config, this.gatewayProperties);\n\t}\n\n\t/**\n\t * Tests the initialization method to ensure that fallback properties are fetched\n\t * and the block exception handler and gateway filter are properly configured.\n\t */\n\t@Test\n\tpublic void testInit() {\n\t\tconfig.init();\n\t\tverify(gatewayProperties).getFallback(); // Check if fallback properties are fetched\n\t\tAssert.assertNotNull(config.sentinelGatewayBlockExceptionHandler());\n\t\tAssert.assertNotNull(config.sentinelGatewayFilter());\n\t}\n\n\t/**\n\t * Tests the initialization method when the fallback mode is set to return a custom response message.\n\t * Verifies that the response status, content type, and body match the expected values.\n\t */\n\t@Test\n\tpublic void testInitWithFallbackMsgResponse() {\n\t\tFallbackProperties fallbackProperties = mock(FallbackProperties.class);\n\t\twhen(gatewayProperties.getFallback()).thenReturn(fallbackProperties);\n\t\twhen(fallbackProperties.getMode()).thenReturn(ConfigConstants.FALLBACK_MSG_RESPONSE);\n\t\twhen(fallbackProperties.getResponseStatus()).thenReturn(200);\n\t\twhen(fallbackProperties.getContentType()).thenReturn(MediaType.APPLICATION_JSON.toString());\n\t\twhen(fallbackProperties.getResponseBody()).thenReturn(\"test\");\n\t\tconfig.init();\n\t\tMono<ServerResponse> responseMono = GatewayCallbackManager.getBlockHandler()\n\t\t\t\t.handleRequest(mock(ServerWebExchange.class), null);\n\t\tAssert.assertEquals(200, Objects.requireNonNull(responseMono.block()).statusCode().value());\n\t}\n\n\t/**\n\t * Tests the initialization method when the fallback mode is set to redirect to another URL.\n\t * Verifies that the response contains the correct redirect location header.\n\t */\n\t@Test\n\tpublic void testInitWithFallbackRedirect() {\n\t\tFallbackProperties fallbackProperties = mock(FallbackProperties.class);\n\t\twhen(gatewayProperties.getFallback()).thenReturn(fallbackProperties);\n\t\twhen(fallbackProperties.getMode()).thenReturn(ConfigConstants.FALLBACK_REDIRECT);\n\t\twhen(fallbackProperties.getRedirect()).thenReturn(\"/test\");\n\t\tconfig.init();\n\t\tMono<ServerResponse> responseMono = GatewayCallbackManager.getBlockHandler()\n\t\t\t\t.handleRequest(mock(ServerWebExchange.class), null);\n\t\tHttpHeaders headers = Objects.requireNonNull(responseMono.block()).headers();\n\t\tList<String> location = headers.get(\"Location\");\n\t\tAssert.assertNotNull(location);\n\t\tAssert.assertEquals(\"/test\", location.get(0));\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/resources/apidefinition.json",
    "content": "[\n  {\n    \"apiName\": \"test\"\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/resources/apidefinition.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<Rules>\n    <FlowRule>\n        <apiName>test</apiName>\n    </FlowRule>\n</Rules>"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/resources/gatewayflowrule.json",
    "content": "[\n  {\n    \"resource\": \"test\",\n    \"resourceMode\": 0,\n    \"grade\": 1,\n    \"count\": 1,\n    \"intervalSec\": 1,\n    \"controlBehavior\": 1,\n    \"burst\": 1,\n    \"maxQueueingTimeoutMs\": 100\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/resources/gatewayflowrule.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<Rules>\n    <FlowRule>\n        <resource>test</resource>\n    </FlowRule>\n</Rules>"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-starters</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>spring-cloud-circuitbreaker-sentinel</artifactId>\n    <name>Spring Cloud Circuit Breaker Sentinel</name>\n\n    <dependencies>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-commons</artifactId>\n        </dependency>\n\n        <!-- Dynamic refresh from config center -->\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-context</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-core</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-reactor-adapter</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>io.projectreactor</groupId>\n            <artifactId>reactor-core</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-openfeign</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <!-- datasource rules -->\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-datasource-extension</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-configuration-processor</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <!-- Testing -->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-webflux</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>io.projectreactor</groupId>\n            <artifactId>reactor-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-restclient</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-resttestclient</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreaker.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.circuitbreaker.sentinel;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.function.Function;\n\nimport com.alibaba.csp.sentinel.EntryType;\nimport com.alibaba.csp.sentinel.adapter.reactor.EntryConfig;\nimport com.alibaba.csp.sentinel.adapter.reactor.SentinelReactorTransformer;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;\nimport reactor.core.publisher.Flux;\nimport reactor.core.publisher.Mono;\n\nimport org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreaker;\nimport org.springframework.util.Assert;\n\n/**\n * Sentinel implementation of {@link ReactiveCircuitBreaker}.\n *\n * @author Eric Zhao\n */\npublic class ReactiveSentinelCircuitBreaker implements ReactiveCircuitBreaker {\n\n\tprivate final String resourceName;\n\n\tprivate final EntryType entryType;\n\n\tprivate final List<DegradeRule> rules;\n\n\tpublic ReactiveSentinelCircuitBreaker(String resourceName, EntryType entryType,\n\t\t\tList<DegradeRule> rules) {\n\t\tAssert.hasText(resourceName, \"resourceName cannot be blank\");\n\t\tAssert.notNull(rules, \"rules should not be null\");\n\t\tthis.resourceName = resourceName;\n\t\tthis.entryType = entryType;\n\t\tthis.rules = Collections.unmodifiableList(rules);\n\n\t\tapplyToSentinelRuleManager();\n\t}\n\n\tpublic ReactiveSentinelCircuitBreaker(String resourceName, List<DegradeRule> rules) {\n\t\tthis(resourceName, EntryType.OUT, rules);\n\t}\n\n\tpublic ReactiveSentinelCircuitBreaker(String resourceName) {\n\t\tthis(resourceName, EntryType.OUT, Collections.emptyList());\n\t}\n\n\tprivate void applyToSentinelRuleManager() {\n\t\tif (this.rules == null || this.rules.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\tSet<DegradeRule> ruleSet = new HashSet<>(DegradeRuleManager.getRules());\n\t\tfor (DegradeRule rule : this.rules) {\n\t\t\tif (rule == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\trule.setResource(resourceName);\n\t\t\truleSet.add(rule);\n\t\t}\n\t\tDegradeRuleManager.loadRules(new ArrayList<>(ruleSet));\n\t}\n\n\t@Override\n\tpublic <T> Mono<T> run(Mono<T> toRun, Function<Throwable, Mono<T>> fallback) {\n\t\tMono<T> toReturn = toRun.transform(new SentinelReactorTransformer<>(\n\t\t\t\tnew EntryConfig(resourceName, entryType)));\n\t\tif (fallback != null) {\n\t\t\ttoReturn = toReturn.onErrorResume(fallback);\n\t\t}\n\t\treturn toReturn;\n\t}\n\n\t@Override\n\tpublic <T> Flux<T> run(Flux<T> toRun, Function<Throwable, Flux<T>> fallback) {\n\t\tFlux<T> toReturn = toRun.transform(new SentinelReactorTransformer<>(\n\t\t\t\tnew EntryConfig(resourceName, entryType)));\n\t\tif (fallback != null) {\n\t\t\ttoReturn = toReturn.onErrorResume(fallback);\n\t\t}\n\t\treturn toReturn;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.circuitbreaker.sentinel;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.cloud.client.circuitbreaker.Customizer;\nimport org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author Eric Zhao\n * @author freeman\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnClass(\n\t\tname = { \"reactor.core.publisher.Mono\", \"reactor.core.publisher.Flux\" })\n@ConditionalOnProperty(name = \"spring.cloud.circuitbreaker.sentinel.enabled\",\n\t\thavingValue = \"true\", matchIfMissing = true)\npublic class ReactiveSentinelCircuitBreakerAutoConfiguration {\n\n\t@Autowired(required = false)\n\tprivate List<Customizer<ReactiveSentinelCircuitBreakerFactory>> customizers = new ArrayList<>();\n\n\t@Bean\n\t@ConditionalOnMissingBean(ReactiveCircuitBreakerFactory.class)\n\tpublic ReactiveCircuitBreakerFactory reactiveSentinelCircuitBreakerFactory() {\n\t\tReactiveSentinelCircuitBreakerFactory factory = new ReactiveSentinelCircuitBreakerFactory();\n\t\tcustomizers.forEach(customizer -> customizer.customize(factory));\n\t\treturn factory;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerFactory.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.circuitbreaker.sentinel;\n\nimport java.util.ArrayList;\nimport java.util.function.Function;\n\nimport com.alibaba.cloud.circuitbreaker.sentinel.SentinelConfigBuilder.SentinelCircuitBreakerConfiguration;\n\nimport org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreaker;\nimport org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory;\nimport org.springframework.util.Assert;\n\n/**\n * Factory for {@link ReactiveSentinelCircuitBreaker}.\n *\n * @author Eric Zhao\n */\npublic class ReactiveSentinelCircuitBreakerFactory extends\n\t\tReactiveCircuitBreakerFactory<SentinelCircuitBreakerConfiguration, SentinelConfigBuilder> {\n\n\tprivate Function<String, SentinelConfigBuilder.SentinelCircuitBreakerConfiguration> defaultConfiguration = id -> new SentinelConfigBuilder()\n\t\t\t.resourceName(id).rules(new ArrayList<>()).build();\n\n\t@Override\n\tpublic ReactiveCircuitBreaker create(String id) {\n\t\tAssert.hasText(id, \"A CircuitBreaker must have an id.\");\n\t\tSentinelConfigBuilder.SentinelCircuitBreakerConfiguration conf = getConfigurations()\n\t\t\t\t.computeIfAbsent(id, defaultConfiguration);\n\t\treturn new ReactiveSentinelCircuitBreaker(id, conf.getEntryType(),\n\t\t\t\tconf.getRules());\n\t}\n\n\t@Override\n\tprotected SentinelConfigBuilder configBuilder(String id) {\n\t\treturn new SentinelConfigBuilder(id);\n\t}\n\n\t@Override\n\tpublic void configureDefault(\n\t\t\tFunction<String, SentinelCircuitBreakerConfiguration> defaultConfiguration) {\n\t\tthis.defaultConfiguration = defaultConfiguration;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.circuitbreaker.sentinel;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.function.Function;\nimport java.util.function.Supplier;\n\nimport com.alibaba.csp.sentinel.Entry;\nimport com.alibaba.csp.sentinel.EntryType;\nimport com.alibaba.csp.sentinel.SphU;\nimport com.alibaba.csp.sentinel.Tracer;\nimport com.alibaba.csp.sentinel.slots.block.BlockException;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;\n\nimport org.springframework.cloud.client.circuitbreaker.CircuitBreaker;\nimport org.springframework.util.Assert;\n\n/**\n * Sentinel implementation of {@link CircuitBreaker}.\n *\n * @author Eric Zhao\n */\npublic class SentinelCircuitBreaker implements CircuitBreaker {\n\n\tprivate final String resourceName;\n\n\tprivate final EntryType entryType;\n\n\tprivate final List<DegradeRule> rules;\n\n\tpublic SentinelCircuitBreaker(String resourceName, EntryType entryType,\n\t\t\tList<DegradeRule> rules) {\n\t\tAssert.hasText(resourceName, \"resourceName cannot be blank\");\n\t\tAssert.notNull(rules, \"rules should not be null\");\n\t\tthis.resourceName = resourceName;\n\t\tthis.entryType = entryType;\n\t\tthis.rules = Collections.unmodifiableList(rules);\n\n\t\tapplyToSentinelRuleManager();\n\t}\n\n\tpublic SentinelCircuitBreaker(String resourceName, List<DegradeRule> rules) {\n\t\tthis(resourceName, EntryType.OUT, rules);\n\t}\n\n\tpublic SentinelCircuitBreaker(String resourceName) {\n\t\tthis(resourceName, EntryType.OUT, Collections.emptyList());\n\t}\n\n\tprivate void applyToSentinelRuleManager() {\n\t\tif (this.rules == null || this.rules.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\tSet<DegradeRule> ruleSet = new HashSet<>(DegradeRuleManager.getRules());\n\t\tfor (DegradeRule rule : this.rules) {\n\t\t\tif (rule == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\trule.setResource(resourceName);\n\t\t\truleSet.add(rule);\n\t\t}\n\t\tDegradeRuleManager.loadRules(new ArrayList<>(ruleSet));\n\t}\n\n\t@Override\n\tpublic <T> T run(Supplier<T> toRun, Function<Throwable, T> fallback) {\n\t\tEntry entry = null;\n\t\ttry {\n\t\t\tentry = SphU.entry(resourceName, entryType);\n\t\t\t// If the SphU.entry() does not throw `BlockException`, it means that the\n\t\t\t// request can pass.\n\t\t\treturn toRun.get();\n\t\t}\n\t\tcatch (BlockException ex) {\n\t\t\t// SphU.entry() may throw BlockException which indicates that\n\t\t\t// the request was rejected (flow control or circuit breaking triggered).\n\t\t\t// So it should not be counted as the business exception.\n\t\t\treturn fallback.apply(ex);\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\t// For other kinds of exceptions, we'll trace the exception count via\n\t\t\t// Tracer.trace(ex).\n\t\t\tTracer.trace(ex);\n\t\t\treturn fallback.apply(ex);\n\t\t}\n\t\tfinally {\n\t\t\t// Guarantee the invocation has been completed.\n\t\t\tif (entry != null) {\n\t\t\t\tentry.exit();\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.circuitbreaker.sentinel;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n\nimport com.alibaba.csp.sentinel.SphU;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;\nimport org.springframework.cloud.client.circuitbreaker.Customizer;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * Auto configuration for {@link SentinelCircuitBreaker}.\n *\n * @author Eric Zhao\n * @author freeman\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnClass({ SphU.class })\n@ConditionalOnProperty(name = \"spring.cloud.circuitbreaker.sentinel.enabled\",\n\t\thavingValue = \"true\", matchIfMissing = true)\npublic class SentinelCircuitBreakerAutoConfiguration {\n\n\t@Autowired(required = false)\n\tprivate List<Customizer<SentinelCircuitBreakerFactory>> customizers = new ArrayList<>();\n\n\t@Bean\n\t@ConditionalOnMissingBean(CircuitBreakerFactory.class)\n\tpublic CircuitBreakerFactory sentinelCircuitBreakerFactory() {\n\t\tSentinelCircuitBreakerFactory factory = new SentinelCircuitBreakerFactory();\n\t\tcustomizers.forEach(customizer -> customizer.customize(factory));\n\t\treturn factory;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.circuitbreaker.sentinel;\n\nimport java.util.ArrayList;\nimport java.util.function.Function;\n\nimport com.alibaba.cloud.circuitbreaker.sentinel.SentinelConfigBuilder.SentinelCircuitBreakerConfiguration;\nimport com.alibaba.csp.sentinel.EntryType;\n\nimport org.springframework.cloud.client.circuitbreaker.CircuitBreaker;\nimport org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;\nimport org.springframework.util.Assert;\n\n/**\n * @author Eric Zhao\n */\npublic class SentinelCircuitBreakerFactory extends\n\t\tCircuitBreakerFactory<SentinelCircuitBreakerConfiguration, SentinelConfigBuilder> {\n\n\tprivate Function<String, SentinelConfigBuilder.SentinelCircuitBreakerConfiguration> defaultConfiguration = id -> new SentinelConfigBuilder()\n\t\t\t.resourceName(id).entryType(EntryType.OUT).rules(new ArrayList<>()).build();\n\n\t@Override\n\tpublic CircuitBreaker create(String id) {\n\t\tAssert.hasText(id, \"A CircuitBreaker must have an id.\");\n\t\tSentinelConfigBuilder.SentinelCircuitBreakerConfiguration conf = getConfigurations()\n\t\t\t\t.computeIfAbsent(id, defaultConfiguration);\n\t\treturn new SentinelCircuitBreaker(id, conf.getEntryType(), conf.getRules());\n\t}\n\n\t@Override\n\tprotected SentinelConfigBuilder configBuilder(String id) {\n\t\treturn new SentinelConfigBuilder(id);\n\t}\n\n\t@Override\n\tpublic void configureDefault(\n\t\t\tFunction<String, SentinelCircuitBreakerConfiguration> defaultConfiguration) {\n\t\tthis.defaultConfiguration = defaultConfiguration;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.circuitbreaker.sentinel;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Optional;\n\nimport com.alibaba.csp.sentinel.EntryType;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\n\nimport org.springframework.cloud.client.circuitbreaker.ConfigBuilder;\nimport org.springframework.util.Assert;\n\n/**\n * @author Eric Zhao\n */\npublic class SentinelConfigBuilder implements\n\t\tConfigBuilder<SentinelConfigBuilder.SentinelCircuitBreakerConfiguration> {\n\n\tprivate String resourceName;\n\n\tprivate EntryType entryType;\n\n\tprivate List<DegradeRule> rules;\n\n\tpublic SentinelConfigBuilder() {\n\t}\n\n\tpublic SentinelConfigBuilder(String resourceName) {\n\t\tthis.resourceName = resourceName;\n\t}\n\n\tpublic SentinelConfigBuilder resourceName(String resourceName) {\n\t\tthis.resourceName = resourceName;\n\t\treturn this;\n\t}\n\n\tpublic SentinelConfigBuilder entryType(EntryType entryType) {\n\t\tthis.entryType = entryType;\n\t\treturn this;\n\t}\n\n\tpublic SentinelConfigBuilder rules(List<DegradeRule> rules) {\n\t\tthis.rules = rules;\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic SentinelCircuitBreakerConfiguration build() {\n\t\tAssert.hasText(resourceName, \"resourceName cannot be empty\");\n\t\tList<DegradeRule> rules = Optional.ofNullable(this.rules)\n\t\t\t\t.orElse(new ArrayList<>());\n\n\t\tEntryType entryType = Optional.ofNullable(this.entryType).orElse(EntryType.OUT);\n\t\treturn new SentinelCircuitBreakerConfiguration()\n\t\t\t\t.setResourceName(this.resourceName).setEntryType(entryType)\n\t\t\t\t.setRules(rules);\n\t}\n\n\tpublic static class SentinelCircuitBreakerConfiguration {\n\n\t\tprivate String resourceName;\n\n\t\tprivate EntryType entryType;\n\n\t\tprivate List<DegradeRule> rules;\n\n\t\tpublic String getResourceName() {\n\t\t\treturn resourceName;\n\t\t}\n\n\t\tpublic SentinelCircuitBreakerConfiguration setResourceName(String resourceName) {\n\t\t\tthis.resourceName = resourceName;\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic EntryType getEntryType() {\n\t\t\treturn entryType;\n\t\t}\n\n\t\tpublic SentinelCircuitBreakerConfiguration setEntryType(EntryType entryType) {\n\t\t\tthis.entryType = entryType;\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic List<DegradeRule> getRules() {\n\t\t\treturn rules;\n\t\t}\n\n\t\tpublic SentinelCircuitBreakerConfiguration setRules(List<DegradeRule> rules) {\n\t\t\tthis.rules = rules;\n\t\t\treturn this;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/feign/CircuitBreakerRuleChangeListener.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.circuitbreaker.sentinel.feign;\n\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.Set;\n\nimport com.alibaba.cloud.circuitbreaker.sentinel.SentinelConfigBuilder;\nimport com.alibaba.csp.sentinel.EntryType;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport tools.jackson.databind.SerializationFeature;\nimport tools.jackson.databind.json.JsonMapper;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.SmartInitializingSingleton;\nimport org.springframework.cloud.client.circuitbreaker.AbstractCircuitBreakerFactory;\nimport org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent;\nimport org.springframework.cloud.openfeign.FeignClient;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.core.annotation.AnnotationUtils;\n\n/**\n * Sentinel circuit breaker config change listener.\n *\n * @author freeman\n * @since 2021.0.1.0\n */\n@SuppressWarnings({ \"unchecked\", \"rawtypes\" })\npublic class CircuitBreakerRuleChangeListener implements ApplicationContextAware,\n\t\tApplicationListener<RefreshScopeRefreshedEvent>, SmartInitializingSingleton {\n\tprivate static final Logger LOGGER = LoggerFactory\n\t\t\t.getLogger(CircuitBreakerRuleChangeListener.class);\n\n\tprivate SentinelFeignClientProperties properties;\n\t/**\n\t * properties backup, prevent rules from being updated every time the container is\n\t * refreshed.\n\t */\n\tprivate SentinelFeignClientProperties propertiesBackup;\n\tprivate AbstractCircuitBreakerFactory circuitBreakerFactory;\n\tprivate ApplicationContext applicationContext;\n\n\t@Override\n\tpublic void onApplicationEvent(RefreshScopeRefreshedEvent event) {\n\t\tensureReady();\n\n\t\t// No need to update the rules\n\t\tif (Objects.equals(properties, propertiesBackup)) {\n\t\t\treturn;\n\t\t}\n\n\t\tclearRules();\n\n\t\t// rebind\n\t\tconfigureDefault();\n\t\tconfigureCustom();\n\n\t\tupdateBackup();\n\n\t\tLOGGER.info(\"Sentinel circuit beaker rules refreshed: \\n\"\n\t\t\t\t+ prettyPrint(properties.getRules()));\n\t}\n\n\t@Override\n\tpublic void setApplicationContext(ApplicationContext applicationContext)\n\t\t\tthrows BeansException {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n\t@Override\n\tpublic void afterSingletonsInstantiated() {\n\t\tthis.propertiesBackup = applicationContext\n\t\t\t\t.getBean(SentinelFeignClientProperties.class).copy();\n\t}\n\n\tprivate void ensureReady() {\n\t\t// Do not inject these beans directly,\n\t\t// as it will cause the bean to be initialized prematurely,\n\t\t// and we don't want to change the initialization order of the beans\n\t\tif (circuitBreakerFactory == null) {\n\t\t\tString[] names = applicationContext\n\t\t\t\t\t.getBeanNamesForType(AbstractCircuitBreakerFactory.class);\n\t\t\tif (names.length >= 1) {\n\t\t\t\tthis.circuitBreakerFactory = applicationContext.getBean(names[0],\n\t\t\t\t\t\tAbstractCircuitBreakerFactory.class);\n\t\t\t}\n\t\t}\n\t\tif (properties == null) {\n\t\t\tthis.properties = applicationContext\n\t\t\t\t\t.getBean(SentinelFeignClientProperties.class);\n\t\t}\n\t}\n\n\tprivate void clearRules() {\n\t\tclearCircuitBreakerFactory();\n\t\tclearFeignClientRulesInDegradeManager();\n\t}\n\n\tprivate void configureDefault() {\n\t\tconfigureDefault(properties, circuitBreakerFactory);\n\t}\n\n\tprivate void configureCustom() {\n\t\tconfigureCustom(properties, circuitBreakerFactory);\n\t}\n\n\tprivate void clearCircuitBreakerFactory() {\n\t\tOptional.ofNullable(getConfigurations(circuitBreakerFactory))\n\t\t\t\t.ifPresent(Map::clear);\n\t}\n\n\tprivate void clearFeignClientRulesInDegradeManager() {\n\t\t// first, clear all manually configured feign clients and methods.\n\t\tpropertiesBackup.getRules().keySet().stream()\n\t\t\t\t.filter(key -> !Objects.equals(key, propertiesBackup.getDefaultRule()))\n\t\t\t\t.forEach(resource -> Optional\n\t\t\t\t\t\t.ofNullable(DegradeRuleManager.getRulesOfResource(resource))\n\t\t\t\t\t\t.ifPresent(Set::clear));\n\n\t\t// Find all feign clients, clear the corresponding rules\n\t\t// NOTE: feign client name cannot be the same as the general resource name !!!\n\t\tArrays.stream(applicationContext.getBeanNamesForAnnotation(FeignClient.class))\n\t\t\t\t// A little trick, FeignClient bean name is full class name.\n\t\t\t\t// Simple exclusions, such as its subclass.\n\t\t\t\t.filter(beanName -> beanName.contains(\".\")).map(beanName -> {\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn Class.forName(beanName);\n\t\t\t\t\t}\n\t\t\t\t\tcatch (ClassNotFoundException ignore) {\n\t\t\t\t\t\t// definitely not a feign client, just ignore\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t}).filter(Objects::nonNull).forEach(clazz -> {\n\t\t\t\t\tFeignClient anno = clazz.getAnnotation(FeignClient.class);\n\t\t\t\t\tif (anno == null || AnnotationUtils.getValue(anno) == null) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tString feignClientName = AnnotationUtils.getValue(anno).toString();\n\t\t\t\t\tOptional.ofNullable(\n\t\t\t\t\t\t\tDegradeRuleManager.getRulesOfResource(feignClientName))\n\t\t\t\t\t\t\t.ifPresent(Set::clear);\n\t\t\t\t});\n\t}\n\n\tprivate void updateBackup() {\n\t\tthis.propertiesBackup = this.properties.copy();\n\t}\n\n\tprivate String prettyPrint(Object o) {\n\t\ttry {\n\t\t\treturn JsonMapper.builder().configure(SerializationFeature.INDENT_OUTPUT, true).build()\n\t\t\t\t\t.writeValueAsString(o);\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tLOGGER.error(\"JSON serialization err.\", e);\n\t\t\treturn \"__JSON format err__\";\n\t\t}\n\t}\n\n\t// static method\n\n\tpublic static void configureCustom(SentinelFeignClientProperties properties,\n\t\t\tAbstractCircuitBreakerFactory factory) {\n\t\tproperties.getRules().forEach((resourceName, degradeRules) -> {\n\t\t\tif (!Objects.equals(properties.getDefaultRule(), resourceName)) {\n\t\t\t\tfactory.configure(builder -> ((SentinelConfigBuilder) builder)\n\t\t\t\t\t\t.rules(properties.getRules().getOrDefault(resourceName,\n\t\t\t\t\t\t\t\tnew ArrayList<>())),\n\t\t\t\t\t\tresourceName);\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic static void configureDefault(SentinelFeignClientProperties properties,\n\t\t\tAbstractCircuitBreakerFactory factory) {\n\t\tList<DegradeRule> defaultConfigurations = properties.getRules()\n\t\t\t\t.getOrDefault(properties.getDefaultRule(), new ArrayList<>());\n\t\tfactory.configureDefault(\n\t\t\t\tresourceName -> new SentinelConfigBuilder(resourceName.toString())\n\t\t\t\t\t\t.entryType(EntryType.OUT).rules(defaultConfigurations).build());\n\t}\n\n\tpublic static Map getConfigurations(\n\t\t\tAbstractCircuitBreakerFactory circuitBreakerFactory) {\n\t\ttry {\n\t\t\tMethod method = AbstractCircuitBreakerFactory.class\n\t\t\t\t\t.getDeclaredMethod(\"getConfigurations\");\n\t\t\tmethod.setAccessible(true);\n\t\t\treturn (Map) method.invoke(circuitBreakerFactory);\n\t\t}\n\t\tcatch (Exception ignored) {\n\t\t}\n\t\treturn Collections.emptyMap();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/feign/FeignClientCircuitNameResolver.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.circuitbreaker.sentinel.feign;\n\nimport java.lang.reflect.Method;\nimport java.util.Map;\n\nimport feign.Feign;\nimport feign.Target;\n\nimport org.springframework.cloud.client.circuitbreaker.AbstractCircuitBreakerFactory;\nimport org.springframework.cloud.openfeign.CircuitBreakerNameResolver;\n\nimport static com.alibaba.cloud.circuitbreaker.sentinel.feign.CircuitBreakerRuleChangeListener.getConfigurations;\n\n/**\n * Feign client circuit breaker name resolver.\n *\n * @author freeman\n * @since 2021.0.1.0\n * @see CircuitBreakerNameResolver\n */\n@SuppressWarnings(\"rawtypes\")\npublic class FeignClientCircuitNameResolver implements CircuitBreakerNameResolver {\n\n\tprivate final Map configurations;\n\n\tpublic FeignClientCircuitNameResolver(AbstractCircuitBreakerFactory factory) {\n\t\tconfigurations = getConfigurations(factory);\n\t}\n\n\t@Override\n\tpublic String resolveCircuitBreakerName(String feignClientName, Target<?> target,\n\t\t\tMethod method) {\n\t\tString key = getKey(feignClientName, target, method);\n\n\t\tif (configurations != null && configurations.containsKey(key)) {\n\t\t\treturn key;\n\t\t}\n\n\t\treturn feignClientName;\n\t}\n\n\tprivate String getKey(String feignClientName, Target<?> target, Method method) {\n\t\tString key = Feign.configKey(target.type(), method);\n\t\treturn feignClientName + key.substring(key.indexOf('#'));\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/feign/SentinelFeignClientAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.circuitbreaker.sentinel.feign;\n\nimport java.util.Collections;\nimport java.util.List;\n\nimport com.alibaba.cloud.circuitbreaker.sentinel.ReactiveSentinelCircuitBreakerFactory;\nimport com.alibaba.cloud.circuitbreaker.sentinel.SentinelCircuitBreakerFactory;\nimport feign.Feign;\n\nimport org.springframework.beans.factory.ObjectProvider;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.cloud.client.circuitbreaker.AbstractCircuitBreakerFactory;\nimport org.springframework.cloud.client.circuitbreaker.Customizer;\nimport org.springframework.cloud.openfeign.CircuitBreakerNameResolver;\nimport org.springframework.cloud.openfeign.FeignClientFactoryBean;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\nimport static com.alibaba.cloud.circuitbreaker.sentinel.feign.CircuitBreakerRuleChangeListener.configureCustom;\nimport static com.alibaba.cloud.circuitbreaker.sentinel.feign.CircuitBreakerRuleChangeListener.configureDefault;\n\n/**\n * Auto configuration for feign client circuit breaker rules.\n *\n * @author freeman\n * @since 2021.0.1.0\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnClass({ Feign.class, FeignClientFactoryBean.class })\n@ConditionalOnProperty(name = \"spring.cloud.circuitbreaker.sentinel.enabled\", havingValue = \"true\", matchIfMissing = true)\n@EnableConfigurationProperties(SentinelFeignClientProperties.class)\npublic class SentinelFeignClientAutoConfiguration {\n\n\t@Configuration(proxyBeanMethods = false)\n\t@ConditionalOnProperty(name = \"feign.sentinel.enable-refresh-rules\", havingValue = \"true\", matchIfMissing = true)\n\tpublic static class CircuitBreakerListenerConfiguration {\n\n\t\t@Bean\n\t\tpublic CircuitBreakerRuleChangeListener circuitBreakerRuleChangeListener() {\n\t\t\treturn new CircuitBreakerRuleChangeListener();\n\t\t}\n\n\t}\n\n\t@Configuration(proxyBeanMethods = false)\n\tpublic static class CircuitBreakerNameResolverConfiguration {\n\n\t\t@Bean\n\t\t@ConditionalOnMissingBean(CircuitBreakerNameResolver.class)\n\t\tpublic CircuitBreakerNameResolver feignClientCircuitNameResolver(\n\t\t\t\tObjectProvider<List<AbstractCircuitBreakerFactory>> provider) {\n\t\t\tList<AbstractCircuitBreakerFactory> factories = provider\n\t\t\t\t\t.getIfAvailable(Collections::emptyList);\n\t\t\tif (factories.size() >= 1) {\n\t\t\t\treturn new FeignClientCircuitNameResolver(factories.get(0));\n\t\t\t}\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"need one CircuitBreakerFactory/ReactiveCircuitBreakerFactory, but 0 found.\");\n\t\t}\n\n\t}\n\n\t@Configuration(proxyBeanMethods = false)\n\tpublic static class SentinelCustomizerConfiguration {\n\n\t\t@Bean\n\t\tpublic Customizer<SentinelCircuitBreakerFactory> configureRulesCustomizer(\n\t\t\t\tSentinelFeignClientProperties properties) {\n\t\t\treturn factory -> {\n\t\t\t\tconfigureDefault(properties, factory);\n\t\t\t\tconfigureCustom(properties, factory);\n\t\t\t};\n\t\t}\n\n\t}\n\n\t@Configuration(proxyBeanMethods = false)\n\t@ConditionalOnClass(name = { \"reactor.core.publisher.Mono\",\n\t\t\t\"reactor.core.publisher.Flux\" })\n\tpublic static class ReactiveSentinelCustomizerConfiguration {\n\n\t\t@Bean\n\t\tpublic Customizer<ReactiveSentinelCircuitBreakerFactory> reactiveConfigureRulesCustomizer(\n\t\t\t\tSentinelFeignClientProperties properties) {\n\t\t\treturn factory -> {\n\t\t\t\tconfigureDefault(properties, factory);\n\t\t\t\tconfigureCustom(properties, factory);\n\t\t\t};\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/feign/SentinelFeignClientProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.circuitbreaker.sentinel.feign;\n\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\n\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\nimport tools.jackson.databind.ObjectMapper;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\n\n/**\n * Sentinel feign client properties.\n *\n * @author freeman\n * @since 2021.0.1.0\n */\n@ConfigurationProperties(\"feign.sentinel\")\npublic class SentinelFeignClientProperties {\n\n\t/**\n\t * default rule name.\n\t */\n\tprivate String defaultRule = \"default\";\n\n\t/**\n\t * enable refresh circuit breaker rules from config center.\n\t */\n\tprivate boolean enableRefreshRules = true;\n\n\tprivate Map<String, List<DegradeRule>> rules = new HashMap<>();\n\n\tpublic String getDefaultRule() {\n\t\treturn defaultRule;\n\t}\n\n\tpublic void setDefaultRule(String defaultRule) {\n\t\tthis.defaultRule = defaultRule;\n\t}\n\n\tpublic boolean isEnableRefreshRules() {\n\t\treturn enableRefreshRules;\n\t}\n\n\tpublic void setEnableRefreshRules(boolean enableRefreshRules) {\n\t\tthis.enableRefreshRules = enableRefreshRules;\n\t}\n\n\tpublic Map<String, List<DegradeRule>> getRules() {\n\t\treturn rules;\n\t}\n\n\tpublic void setRules(Map<String, List<DegradeRule>> rules) {\n\t\tthis.rules = rules;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (this == o) {\n\t\t\treturn true;\n\t\t}\n\t\tif (o == null || getClass() != o.getClass()) {\n\t\t\treturn false;\n\t\t}\n\t\tSentinelFeignClientProperties that = (SentinelFeignClientProperties) o;\n\t\treturn enableRefreshRules == that.enableRefreshRules\n\t\t\t\t&& Objects.equals(defaultRule, that.defaultRule)\n\t\t\t\t&& Objects.equals(rules, that.rules);\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn Objects.hash(defaultRule, enableRefreshRules, rules);\n\t}\n\n\tpublic SentinelFeignClientProperties copy() {\n\t\ttry {\n\t\t\tObjectMapper objectMapper = new ObjectMapper();\n\t\t\tString json = objectMapper.writeValueAsString(this);\n\t\t\treturn objectMapper.readValue(json, this.getClass());\n\t\t}\n\t\tcatch (Exception ignored) {\n\t\t}\n\t\treturn new SentinelFeignClientProperties();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json",
    "content": "{\"properties\": [\n    {\n      \"name\": \"spring.cloud.circuitbreaker.sentinel.enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"description\": \"enable sentinel circuitbreaker or not.\"\n    }\n]}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports",
    "content": "com.alibaba.cloud.circuitbreaker.sentinel.SentinelCircuitBreakerAutoConfiguration\ncom.alibaba.cloud.circuitbreaker.sentinel.ReactiveSentinelCircuitBreakerAutoConfiguration\ncom.alibaba.cloud.circuitbreaker.sentinel.feign.SentinelFeignClientAutoConfiguration\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/test/java/com/alibaba/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerIntegrationTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.circuitbreaker.sentinel;\n\nimport java.time.Duration;\nimport java.util.Collections;\n\nimport com.alibaba.csp.sentinel.slots.block.RuleConstant;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport reactor.core.publisher.Flux;\nimport reactor.core.publisher.Mono;\nimport reactor.test.StepVerifier;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.boot.test.web.server.LocalServerPort;\nimport org.springframework.cloud.client.circuitbreaker.Customizer;\nimport org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.ParameterizedTypeReference;\nimport org.springframework.stereotype.Service;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.reactive.function.client.WebClient;\n\nimport static com.alibaba.cloud.circuitbreaker.sentinel.ReactiveSentinelCircuitBreakerIntegrationTest.Application;\nimport static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;\n\n/**\n * @author Ryan Baxter\n */\n@SpringBootTest(webEnvironment = RANDOM_PORT, classes = Application.class, properties = {\n\t\t\"spring.cloud.discovery.client.health-indicator.enabled=false\" })\npublic class ReactiveSentinelCircuitBreakerIntegrationTest {\n\n\t@LocalServerPort\n\tprivate int port = 0;\n\n\t@Autowired\n\tprivate Application.DemoControllerService service;\n\n\t@BeforeEach\n\tpublic void setup() {\n\t\tservice.setPort(port);\n\t}\n\n\t@Test\n\tpublic void test() throws Exception {\n\t\tStepVerifier.create(service.normal()).expectNext(\"normal\").verifyComplete();\n\t\tStepVerifier.create(service.slow()).expectNext(\"slow\").verifyComplete();\n\t\tStepVerifier.create(service.slow()).expectNext(\"slow\").verifyComplete();\n\t\tStepVerifier.create(service.slow()).expectNext(\"slow\").verifyComplete();\n\t\tStepVerifier.create(service.slow()).expectNext(\"slow\").verifyComplete();\n\t\tStepVerifier.create(service.slow()).expectNext(\"slow\").verifyComplete();\n\n\t\t// Then in the next 5s, the fallback method should be called.\n\t\tfor (int i = 0; i < 5; i++) {\n\t\t\tStepVerifier.create(service.slow()).expectNext(\"fallback\").verifyComplete();\n\t\t\tThread.sleep(900);\n\t\t}\n\t\tThread.sleep(500);\n\n\t\t// Half-open recovery (will re-open the circuit breaker).\n\t\tStepVerifier.create(service.slow()).expectNext(\"slow\").verifyComplete();\n\n\t\tStepVerifier.create(service.normalFlux()).expectNext(\"normalflux\")\n\t\t\t\t.verifyComplete();\n\t\tStepVerifier.create(service.slowFlux()).expectNext(\"slowflux\").verifyComplete();\n\t\tStepVerifier.create(service.slowFlux()).expectNext(\"slowflux\").verifyComplete();\n\t\tStepVerifier.create(service.slowFlux()).expectNext(\"slowflux\").verifyComplete();\n\t\tStepVerifier.create(service.slowFlux()).expectNext(\"slowflux\").verifyComplete();\n\t\tStepVerifier.create(service.slowFlux()).expectNext(\"slowflux\").verifyComplete();\n\t\t// Then in the next 5s, the fallback method should be called.\n\t\tfor (int i = 0; i < 5; i++) {\n\t\t\tStepVerifier.create(service.slowFlux()).expectNext(\"flux_fallback\")\n\t\t\t\t\t.verifyComplete();\n\t\t\tThread.sleep(900);\n\t\t}\n\t\tThread.sleep(500);\n\n\t\t// Half-open recovery (will re-open the circuit breaker).\n\t\tStepVerifier.create(service.slowFlux()).expectNext(\"slowflux\").verifyComplete();\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@RestController\n\tprotected static class Application {\n\n\t\t@GetMapping(\"/slow\")\n\t\tpublic Mono<String> slow() {\n\t\t\treturn Mono.just(\"slow\").delayElement(Duration.ofMillis(80));\n\t\t}\n\n\t\t@GetMapping(\"/normal\")\n\t\tpublic Mono<String> normal() {\n\t\t\treturn Mono.just(\"normal\");\n\t\t}\n\n\t\t@GetMapping(\"/slow_flux\")\n\t\tpublic Flux<String> slowFlux() {\n\t\t\treturn Flux.just(\"slow\", \"flux\").delayElements(Duration.ofMillis(80));\n\t\t}\n\n\t\t@GetMapping(\"normal_flux\")\n\t\tpublic Flux<String> normalFlux() {\n\t\t\treturn Flux.just(\"normal\", \"flux\");\n\t\t}\n\n\t\t@Bean\n\t\tpublic Customizer<ReactiveSentinelCircuitBreakerFactory> slowCustomizer() {\n\t\t\treturn factory -> {\n\t\t\t\tfactory.configure(\n\t\t\t\t\t\tbuilder -> builder.rules(Collections\n\t\t\t\t\t\t\t\t.singletonList(new DegradeRule(\"slow_mono\").setCount(50)\n\t\t\t\t\t\t\t\t\t\t.setSlowRatioThreshold(0.7).setMinRequestAmount(5)\n\t\t\t\t\t\t\t\t\t\t.setStatIntervalMs(30000).setTimeWindow(5))),\n\t\t\t\t\t\t\"slow_mono\");\n\t\t\t\tfactory.configure(\n\t\t\t\t\t\tbuilder -> builder.rules(Collections\n\t\t\t\t\t\t\t\t.singletonList(new DegradeRule(\"slow_mono\").setCount(50)\n\t\t\t\t\t\t\t\t\t\t.setSlowRatioThreshold(0.7).setMinRequestAmount(5)\n\t\t\t\t\t\t\t\t\t\t.setStatIntervalMs(30000).setTimeWindow(5))),\n\t\t\t\t\t\t\"slow_flux\");\n\t\t\t\tfactory.configureDefault(id -> new SentinelConfigBuilder()\n\t\t\t\t\t\t.resourceName(id)\n\t\t\t\t\t\t.rules(Collections.singletonList(new DegradeRule(id)\n\t\t\t\t\t\t\t\t.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT)\n\t\t\t\t\t\t\t\t.setCount(5).setTimeWindow(10)))\n\t\t\t\t\t\t.build());\n\t\t\t};\n\t\t}\n\n\t\t@Service\n\t\tpublic static class DemoControllerService {\n\n\t\t\tprivate int port = 0;\n\n\t\t\tprivate ReactiveCircuitBreakerFactory cbFactory;\n\n\t\t\tDemoControllerService(ReactiveCircuitBreakerFactory cbFactory) {\n\t\t\t\tthis.cbFactory = cbFactory;\n\t\t\t}\n\n\t\t\tpublic Mono<String> slow() {\n\t\t\t\treturn WebClient.builder().baseUrl(\"http://localhost:\" + port).build()\n\t\t\t\t\t\t.get().uri(\"/slow\").retrieve().bodyToMono(String.class)\n\t\t\t\t\t\t.transform(it -> cbFactory.create(\"slow_mono\").run(it, t -> {\n\t\t\t\t\t\t\tt.printStackTrace();\n\t\t\t\t\t\t\treturn Mono.just(\"fallback\");\n\t\t\t\t\t\t}));\n\t\t\t}\n\n\t\t\tpublic Mono<String> normal() {\n\t\t\t\treturn WebClient.builder().baseUrl(\"http://localhost:\" + port).build()\n\t\t\t\t\t\t.get().uri(\"/normal\").retrieve().bodyToMono(String.class)\n\t\t\t\t\t\t.transform(it -> cbFactory.create(\"normal_mono\").run(it, t -> {\n\t\t\t\t\t\t\tt.printStackTrace();\n\t\t\t\t\t\t\treturn Mono.just(\"fallback\");\n\t\t\t\t\t\t}));\n\t\t\t}\n\n\t\t\tpublic Flux<String> slowFlux() {\n\t\t\t\treturn WebClient.builder().baseUrl(\"http://localhost:\" + port).build()\n\t\t\t\t\t\t.get().uri(\"/slow_flux\").retrieve()\n\t\t\t\t\t\t.bodyToFlux(new ParameterizedTypeReference<String>() {\n\t\t\t\t\t\t}).transform(it -> cbFactory.create(\"slow_flux\").run(it, t -> {\n\t\t\t\t\t\t\tt.printStackTrace();\n\t\t\t\t\t\t\treturn Flux.just(\"flux_fallback\");\n\t\t\t\t\t\t}));\n\t\t\t}\n\n\t\t\tpublic Flux<String> normalFlux() {\n\t\t\t\treturn WebClient.builder().baseUrl(\"http://localhost:\" + port).build()\n\t\t\t\t\t\t.get().uri(\"/normal_flux\").retrieve().bodyToFlux(String.class)\n\t\t\t\t\t\t.transform(it -> cbFactory.create(\"normal_flux\").run(it, t -> {\n\t\t\t\t\t\t\tt.printStackTrace();\n\t\t\t\t\t\t\treturn Flux.just(\"flux_fallback\");\n\t\t\t\t\t\t}));\n\t\t\t}\n\n\t\t\tpublic void setPort(int port) {\n\t\t\t\tthis.port = port;\n\t\t\t}\n\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/test/java/com/alibaba/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.circuitbreaker.sentinel;\n\nimport java.util.Arrays;\nimport java.util.Collections;\n\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;\nimport org.junit.jupiter.api.Test;\nimport reactor.core.publisher.Flux;\nimport reactor.core.publisher.Mono;\n\nimport org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreaker;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Eric Zhao\n */\npublic class ReactiveSentinelCircuitBreakerTest {\n\n\t@Test\n\tpublic void testCreateWithNullRule() {\n\t\tString id = \"testCreateReactiveCbWithNullRule\";\n\t\tReactiveSentinelCircuitBreaker cb = new ReactiveSentinelCircuitBreaker(id,\n\t\t\t\tCollections.singletonList(null));\n\t\tassertThat(Mono.just(\"foobar\").transform(it -> cb.run(it)).block())\n\t\t\t\t.isEqualTo(\"foobar\");\n\t\tassertThat(DegradeRuleManager.hasConfig(id)).isFalse();\n\t}\n\n\t@Test\n\tpublic void runMono() {\n\t\tReactiveCircuitBreaker cb = new ReactiveSentinelCircuitBreakerFactory()\n\t\t\t\t.create(\"foo\");\n\t\tassertThat(Mono.just(\"foobar\").transform(it -> cb.run(it)).block())\n\t\t\t\t.isEqualTo(\"foobar\");\n\t}\n\n\t@Test\n\tpublic void runMonoWithFallback() {\n\t\tReactiveCircuitBreaker cb = new ReactiveSentinelCircuitBreakerFactory()\n\t\t\t\t.create(\"foo\");\n\t\tassertThat(Mono.error(new RuntimeException(\"boom\"))\n\t\t\t\t.transform(it -> cb.run(it, t -> Mono.just(\"fallback\"))).block())\n\t\t\t\t\t\t.isEqualTo(\"fallback\");\n\t}\n\n\t@Test\n\tpublic void runFlux() {\n\t\tReactiveCircuitBreaker cb = new ReactiveSentinelCircuitBreakerFactory()\n\t\t\t\t.create(\"foo\");\n\t\tassertThat(Flux.just(\"foobar\", \"hello world\").transform(it -> cb.run(it))\n\t\t\t\t.collectList().block()).isEqualTo(Arrays.asList(\"foobar\", \"hello world\"));\n\t}\n\n\t@Test\n\tpublic void runFluxWithFallback() {\n\t\tReactiveCircuitBreaker cb = new ReactiveSentinelCircuitBreakerFactory()\n\t\t\t\t.create(\"foo\");\n\t\tassertThat(Flux.error(new RuntimeException(\"boom\"))\n\t\t\t\t.transform(it -> cb.run(it, t -> Flux.just(\"fallback\"))).collectList()\n\t\t\t\t.block()).isEqualTo(Arrays.asList(\"fallback\"));\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/test/java/com/alibaba/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerIntegrationTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.circuitbreaker.sentinel;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\nimport com.alibaba.csp.sentinel.slots.block.RuleConstant;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.resttestclient.TestRestTemplate;\nimport org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;\nimport org.springframework.cloud.client.circuitbreaker.Customizer;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.stereotype.Service;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;\n\n/**\n * @author Eric Zhao\n */\n@AutoConfigureTestRestTemplate\n@SpringBootTest(webEnvironment = RANDOM_PORT,\n\t\tclasses = SentinelCircuitBreakerIntegrationTest.Application.class,\n\t\tproperties = { \"spring.cloud.discovery.client.health-indicator.enabled=false\" })\npublic class SentinelCircuitBreakerIntegrationTest {\n\n\t@Autowired\n\tprivate Application.DemoControllerService service;\n\n\t@Test\n\tpublic void testSlow() throws Exception {\n\t\tassertThat(service.slow(true)).isEqualTo(\"slow\");\n\t\tassertThat(service.slow(true)).isEqualTo(\"slow\");\n\t\tassertThat(service.slow(true)).isEqualTo(\"slow\");\n\t\tassertThat(service.slow(false)).isEqualTo(\"slow\");\n\t\tassertThat(service.slow(false)).isEqualTo(\"slow\");\n\t\tassertThat(service.slow(true)).isEqualTo(\"slow\");\n\t\tassertThat(service.slow(true)).isEqualTo(\"slow\");\n\n\t\t// Then in the next 10s, the fallback method should be called.\n\t\tfor (int i = 0; i < 5; i++) {\n\t\t\tassertThat(service.slow(true)).isEqualTo(\"fallback\");\n\t\t\tThread.sleep(1000);\n\t\t}\n\n\t\t// Try a normal request.\n\t\tassertThat(service.slow(false)).isEqualTo(\"slow\");\n\t\t// Recovered.\n\t\tassertThat(service.slow(true)).isEqualTo(\"slow\");\n\t}\n\n\t@Test\n\tpublic void testNormal() {\n\t\tassertThat(service.normal()).isEqualTo(\"normal\");\n\t}\n\n\t@BeforeEach\n\tpublic void setUp() {\n\t\tDegradeRuleManager.loadRules(new ArrayList<>());\n\t}\n\n\t@BeforeEach\n\tpublic void tearDown() {\n\t\tDegradeRuleManager.loadRules(new ArrayList<>());\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@RestController\n\tprotected static class Application {\n\n\t\t@GetMapping(\"/slow\")\n\t\tpublic String slow(@RequestParam(required = false) Boolean slow)\n\t\t\t\tthrows InterruptedException {\n\t\t\tif (slow == null || slow) {\n\t\t\t\tThread.sleep(80);\n\t\t\t}\n\t\t\treturn \"slow\";\n\t\t}\n\n\t\t@GetMapping(\"/normal\")\n\t\tpublic String normal() {\n\t\t\treturn \"normal\";\n\t\t}\n\n\t\t@Bean\n\t\tpublic Customizer<SentinelCircuitBreakerFactory> slowCustomizer() {\n\t\t\tString slowId = \"slow\";\n\t\t\tList<DegradeRule> rules = Collections.singletonList(new DegradeRule(slowId)\n\t\t\t\t\t.setGrade(RuleConstant.DEGRADE_GRADE_RT).setCount(50)\n\t\t\t\t\t.setSlowRatioThreshold(0.7).setMinRequestAmount(5)\n\t\t\t\t\t.setStatIntervalMs(30000).setTimeWindow(5));\n\t\t\treturn factory -> {\n\t\t\t\tfactory.configure(builder -> builder.rules(rules), slowId);\n\t\t\t\tfactory.configureDefault(id -> new SentinelConfigBuilder()\n\t\t\t\t\t\t.resourceName(id)\n\t\t\t\t\t\t.rules(Collections.singletonList(new DegradeRule(id)\n\t\t\t\t\t\t\t\t.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT)\n\t\t\t\t\t\t\t\t.setCount(10).setStatIntervalMs(10000).setTimeWindow(10)))\n\t\t\t\t\t\t.build());\n\t\t\t};\n\t\t}\n\n\t\t@Service\n\t\tpublic static class DemoControllerService {\n\n\t\t\tprivate TestRestTemplate rest;\n\n\t\t\tprivate CircuitBreakerFactory cbFactory;\n\n\t\t\tDemoControllerService(TestRestTemplate rest,\n\t\t\t\t\tCircuitBreakerFactory cbFactory) {\n\t\t\t\tthis.rest = rest;\n\t\t\t\tthis.cbFactory = cbFactory;\n\t\t\t}\n\n\t\t\tpublic String slow(boolean slow) {\n\t\t\t\treturn cbFactory.create(\"slow\").run(\n\t\t\t\t\t\t() -> rest.getForObject(\"/slow?slow=\" + slow, String.class),\n\t\t\t\t\t\tt -> \"fallback\");\n\t\t\t}\n\n\t\t\tpublic String normal() {\n\t\t\t\treturn cbFactory.create(\"normal\").run(\n\t\t\t\t\t\t() -> rest.getForObject(\"/normal\", String.class),\n\t\t\t\t\t\tt -> \"fallback\");\n\t\t\t}\n\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/test/java/com/alibaba/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.circuitbreaker.sentinel;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\n\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.cloud.client.circuitbreaker.CircuitBreaker;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Eric Zhao\n */\npublic class SentinelCircuitBreakerTest {\n\n\t@AfterEach\n\tpublic void tearDown() {\n\t\t// Clear the rules.\n\t\tDegradeRuleManager.loadRules(new ArrayList<>());\n\t}\n\n\t@Test\n\tpublic void testCreateDirectlyThenRun() {\n\t\t// Create a circuit breaker without any circuit breaking rules.\n\t\tCircuitBreaker cb = new SentinelCircuitBreaker(\n\t\t\t\t\"testSentinelCreateDirectlyThenRunA\");\n\t\tassertThat(cb.run(() -> \"Sentinel\")).isEqualTo(\"Sentinel\");\n\t\tassertThat(DegradeRuleManager.hasConfig(\"testSentinelCreateDirectlyThenRunA\"))\n\t\t\t\t.isFalse();\n\n\t\tCircuitBreaker cb2 = new SentinelCircuitBreaker(\n\t\t\t\t\"testSentinelCreateDirectlyThenRunB\",\n\t\t\t\tCollections.singletonList(\n\t\t\t\t\t\tnew DegradeRule(\"testSentinelCreateDirectlyThenRunB\")\n\t\t\t\t\t\t\t\t.setCount(100).setTimeWindow(10)));\n\t\tassertThat(cb2.run(() -> \"Sentinel\")).isEqualTo(\"Sentinel\");\n\t\tassertThat(DegradeRuleManager.hasConfig(\"testSentinelCreateDirectlyThenRunB\"))\n\t\t\t\t.isTrue();\n\t}\n\n\t@Test\n\tpublic void testCreateWithNullRule() {\n\t\tString id = \"testCreateCbWithNullRule\";\n\t\tCircuitBreaker cb = new SentinelCircuitBreaker(id,\n\t\t\t\tCollections.singletonList(null));\n\t\tassertThat(cb.run(() -> \"Sentinel\")).isEqualTo(\"Sentinel\");\n\t\tassertThat(DegradeRuleManager.hasConfig(id)).isFalse();\n\t}\n\n\t@Test\n\tpublic void testCreateFromFactoryThenRun() {\n\t\tCircuitBreaker cb = new SentinelCircuitBreakerFactory().create(\"testSentinelRun\");\n\t\tassertThat(cb.run(() -> \"foobar\")).isEqualTo(\"foobar\");\n\t}\n\n\t@Test\n\tpublic void testRunWithFallback() {\n\t\tCircuitBreaker cb = new SentinelCircuitBreakerFactory()\n\t\t\t\t.create(\"testSentinelRunWithFallback\");\n\t\tassertThat(cb.<String>run(() -> {\n\t\t\tthrow new RuntimeException(\"boom\");\n\t\t}, t -> \"fallback\")).isEqualTo(\"fallback\");\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/test/java/com/alibaba/cloud/circuitbreaker/sentinel/feign/FeignClientCircuitBreakerRuleIntegrationTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.circuitbreaker.sentinel.feign;\n\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.cloud.openfeign.EnableFeignClients;\nimport org.springframework.cloud.openfeign.FeignClient;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport static com.alibaba.cloud.circuitbreaker.sentinel.feign.FeignClientCircuitBreakerRuleIntegrationTest.Application;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT;\n\n/**\n * @author freeman\n */\n@SpringBootTest(webEnvironment = DEFINED_PORT, classes = Application.class, properties = {\n\t\t\"server.port=10101\",\n\t\t\"spring.cloud.openfeign.circuitbreaker.enabled=true\",\n\t\t\"feign.sentinel.default-rule=default\",\n\t\t\"feign.sentinel.rules.default[0].grade=2\",\n\t\t\"feign.sentinel.rules.default[0].count=2\",\n\t\t\"feign.sentinel.rules.default[0].timeWindow=1\",\n\t\t\"feign.sentinel.rules.default[0].statIntervalMs=30000\",\n\t\t\"feign.sentinel.rules.default[0].minRequestAmount=5\",\n\t\t\"feign.sentinel.rules.user[0].grade=2\",\n\t\t\"feign.sentinel.rules.user[0].count=2\",\n\t\t\"feign.sentinel.rules.user[0].timeWindow=1\",\n\t\t\"feign.sentinel.rules.user[0].statIntervalMs=30000\",\n\t\t\"feign.sentinel.rules.user[0].minRequestAmount=5\",\n\t\t\"feign.sentinel.rules.[user#specificFeignMethod(boolean)][0].grade=2\",\n\t\t\"feign.sentinel.rules.[user#specificFeignMethod(boolean)][0].count=1\",\n\t\t\"feign.sentinel.rules.[user#specificFeignMethod(boolean)][0].timeWindow=1\",\n\t\t\"feign.sentinel.rules.[user#specificFeignMethod(boolean)][0].statIntervalMs=30000\",\n\t\t\"feign.sentinel.rules.[user#specificFeignMethod(boolean)][0].minRequestAmount=5\"\n})\npublic class FeignClientCircuitBreakerRuleIntegrationTest {\n\n\t@Autowired\n\tprivate Application.UserClient userClient;\n\t@Autowired\n\tprivate Application.OrderClient orderClient;\n\n\t@Test\n\tpublic void testDefaultRule() throws Exception {\n\t\t// test default configuration is working\n\n\t\t// ok\n\t\tassertThat(orderClient.defaultConfig(true)).isEqualTo(\"ok\");\n\t\tassertThat(orderClient.defaultConfig(true)).isEqualTo(\"ok\");\n\t\tassertThat(orderClient.defaultConfig(true)).isEqualTo(\"ok\");\n\t\tassertThat(orderClient.defaultConfig(true)).isEqualTo(\"ok\");\n\t\tassertThat(orderClient.defaultConfig(true)).isEqualTo(\"ok\");\n\n\t\t// occur exception\n\t\tassertThat(orderClient.defaultConfig(false)).isEqualTo(\"fallback\");\n\t\tassertThat(orderClient.defaultConfig(false)).isEqualTo(\"fallback\");\n\t\t// the 3rd exception, circuit breaker open\n\t\tassertThat(orderClient.defaultConfig(false)).isEqualTo(\"fallback\");\n\n\t\t// sleep 300, ensure circuit breaker status is open.\n\t\tThread.sleep(300);\n\n\t\t// test circuit breaker open\n\t\tassertThat(orderClient.defaultConfig(true)).isEqualTo(\"fallback\");\n\t\tassertThat(orderClient.defaultConfig(false)).isEqualTo(\"fallback\");\n\n\t\t// longer than timeWindow, circuit breaker half open\n\t\tThread.sleep(1200L);\n\n\t\t// let circuit breaker close\n\t\tassertThat(orderClient.defaultConfig(true)).isEqualTo(\"ok\");\n\t\tassertThat(orderClient.defaultConfig(false)).isEqualTo(\"fallback\");\n\t}\n\n\t@Test\n\tpublic void testSpecificFeignRule() throws Exception {\n\t\t// test specific Feign client configuration is working\n\n\t\t// ok\n\t\tassertThat(userClient.specificFeign(true)).isEqualTo(\"ok\");\n\t\tassertThat(userClient.specificFeign(true)).isEqualTo(\"ok\");\n\t\tassertThat(userClient.specificFeign(true)).isEqualTo(\"ok\");\n\t\tassertThat(userClient.specificFeign(true)).isEqualTo(\"ok\");\n\t\tassertThat(userClient.specificFeign(true)).isEqualTo(\"ok\");\n\n\t\t// occur exception\n\t\tassertThat(userClient.specificFeign(false)).isEqualTo(\"fallback\");\n\t\tassertThat(userClient.specificFeign(false)).isEqualTo(\"fallback\");\n\t\t// the 3rd exception, circuit breaker open\n\t\tassertThat(userClient.specificFeign(false)).isEqualTo(\"fallback\");\n\n\t\tThread.sleep(300);\n\n\t\t// test circuit breaker open\n\t\tassertThat(userClient.specificFeign(true)).isEqualTo(\"fallback\");\n\t\tassertThat(userClient.specificFeign(false)).isEqualTo(\"fallback\");\n\n\t\t// longer than timeWindow, circuit breaker half open\n\t\tThread.sleep(1200L);\n\n\t\t// let circuit breaker close\n\t\tassertThat(userClient.specificFeign(true)).isEqualTo(\"ok\");\n\t\tassertThat(userClient.specificFeign(false)).isEqualTo(\"fallback\");\n\t}\n\n\t@Test\n\tpublic void testSpecificFeignMethodRule() throws Exception {\n\t\t// test specific Feign client method configuration is working\n\n\t\t// ok\n\t\tassertThat(userClient.specificFeignMethod(true)).isEqualTo(\"ok\");\n\t\tassertThat(userClient.specificFeignMethod(true)).isEqualTo(\"ok\");\n\t\tassertThat(userClient.specificFeignMethod(true)).isEqualTo(\"ok\");\n\t\tassertThat(userClient.specificFeignMethod(true)).isEqualTo(\"ok\");\n\t\tassertThat(userClient.specificFeignMethod(true)).isEqualTo(\"ok\");\n\n\t\t// occur exception\n\t\tassertThat(userClient.specificFeignMethod(false)).isEqualTo(\"fallback\");\n\t\t// occur the 2nd exception, circuit breaker open\n\t\tassertThat(userClient.specificFeignMethod(false)).isEqualTo(\"fallback\");\n\n\t\tThread.sleep(300);\n\n\t\t// test circuit breaker is open\n\t\tassertThat(userClient.specificFeignMethod(true)).isEqualTo(\"fallback\");\n\t\tassertThat(userClient.specificFeignMethod(false)).isEqualTo(\"fallback\");\n\n\t\t// longer than timeWindow, circuit breaker half open\n\t\tThread.sleep(1200L);\n\n\t\t// let circuit breaker close\n\t\tassertThat(userClient.specificFeignMethod(true)).isEqualTo(\"ok\");\n\t\tassertThat(userClient.specificFeignMethod(false)).isEqualTo(\"fallback\");\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@RestController\n\t@EnableFeignClients\n\tprotected static class Application {\n\n\t\t@FeignClient(value = \"user\", url = \"http://localhost:${server.port}\", fallback = UserClientFallback.class)\n\t\tinterface UserClient {\n\n\t\t\t@GetMapping(\"/specificFeign/{success}\")\n\t\t\tString specificFeign(@PathVariable boolean success);\n\n\t\t\t@GetMapping(\"/specificFeignMethod/{success}\")\n\t\t\tString specificFeignMethod(@PathVariable boolean success);\n\n\t\t}\n\n\t\t@FeignClient(value = \"order\", url = \"http://localhost:${server.port}\", fallback = OrderClientFallback.class)\n\t\tinterface OrderClient {\n\n\t\t\t@GetMapping(\"/defaultConfig/{success}\")\n\t\t\tString defaultConfig(@PathVariable boolean success);\n\n\t\t}\n\n\t\t@Component\n\t\tstatic class UserClientFallback implements UserClient {\n\n\t\t\t@Override\n\t\t\tpublic String specificFeign(boolean success) {\n\t\t\t\treturn \"fallback\";\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic String specificFeignMethod(boolean success) {\n\t\t\t\treturn \"fallback\";\n\t\t\t}\n\n\t\t}\n\n\t\t@Component\n\t\tstatic class OrderClientFallback implements OrderClient {\n\n\t\t\t@Override\n\t\t\tpublic String defaultConfig(boolean success) {\n\t\t\t\treturn \"fallback\";\n\t\t\t}\n\n\t\t}\n\n\t\t@RestController\n\t\tstatic class TestController {\n\n\t\t\t@GetMapping(\"/specificFeign/{success}\")\n\t\t\tpublic String specificFeign(@PathVariable boolean success) {\n\t\t\t\tif (success) {\n\t\t\t\t\treturn \"ok\";\n\t\t\t\t}\n\t\t\t\tthrow new RuntimeException(\"failed\");\n\t\t\t}\n\n\t\t\t@GetMapping(\"/defaultConfig/{success}\")\n\t\t\tString defaultConfig(@PathVariable boolean success) {\n\t\t\t\tif (success) {\n\t\t\t\t\treturn \"ok\";\n\t\t\t\t}\n\t\t\t\tthrow new RuntimeException(\"failed\");\n\t\t\t}\n\n\t\t\t@GetMapping(\"/specificFeignMethod/{success}\")\n\t\t\tString specificFeignMethod(@PathVariable boolean success) {\n\t\t\t\tif (success) {\n\t\t\t\t\treturn \"ok\";\n\t\t\t\t}\n\t\t\t\tthrow new RuntimeException(\"failed\");\n\t\t\t}\n\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-starters</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>\n    <name>Spring Cloud Starter Alibaba Nacos Config</name>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-alibaba-commons</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-alibaba-nacos-config</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-actuator-autoconfigure</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-configuration-processor</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-client</artifactId>\n        </dependency>\n\n        <!--spring cloud-->\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-commons</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-context</artifactId>\n        </dependency>\n\n        <!-- Testing -->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n    \n        <dependency>\n            <groupId>jakarta.annotation</groupId>\n            <artifactId>jakarta.annotation-api</artifactId>\n        </dependency>\n        \n    </dependencies>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigSpringCloudAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\nimport com.alibaba.cloud.nacos.configdata.NacosConfigRefreshEventListener;\nimport com.alibaba.cloud.nacos.refresh.SmartConfigurationPropertiesRebinder;\nimport com.alibaba.cloud.nacos.refresh.condition.ConditionalOnNonDefaultBehavior;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.boot.autoconfigure.condition.SearchStrategy;\nimport org.springframework.cloud.context.properties.ConfigurationPropertiesBeans;\nimport org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author juven.xuxb\n * @author freeman\n */\n@Configuration(proxyBeanMethods = false)\n@Conditional(NacosConfigEnabledCondition.class)\npublic class NacosConfigSpringCloudAutoConfiguration {\n\n\t@Bean\n\t@ConditionalOnMissingBean(search = SearchStrategy.CURRENT)\n\t@ConditionalOnNonDefaultBehavior\n\tpublic ConfigurationPropertiesRebinder smartConfigurationPropertiesRebinder(ConfigurationPropertiesBeans beans) {\n\t\t// If using default behavior, not use SmartConfigurationPropertiesRebinder.\n\t\t// Minimize te possibility of making mistakes.\n\t\treturn new SmartConfigurationPropertiesRebinder(beans);\n\t}\n\n\t@Bean(name = \"nacosConfigSpringCloudRefreshEventListener\")\n\tpublic NacosConfigRefreshEventListener nacosConfigRefreshEventListener() {\n\t\treturn new NacosConfigRefreshEventListener();\n\t}\n\n\t@Configuration(proxyBeanMethods = false)\n\t@ConditionalOnProperty(name = \"spring.cloud.nacos.config.enable-check-bootstrap\", matchIfMissing = true)\n\t@ConditionalOnClass(name = \"org.springframework.cloud.bootstrap.marker.Marker\")\n\tstatic class BootstrapDetectionConfiguration {\n\t\tBootstrapDetectionConfiguration() {\n\t\t\tLoggerFactory.getLogger(BootstrapDetectionConfiguration.class)\n\t\t\t\t\t.warn(\"Including 'org.springframework.cloud:spring-cloud-starter-bootstrap' will prevent Nacos Config from working properly.\"\n\t\t\t\t\t+ \"Please remove this dependency. For details, please refer to: https://github.com/alibaba/spring-cloud-alibaba/issues/4259\");\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/SpringCloudNacosPropertiesPrefixProvider.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\npublic class SpringCloudNacosPropertiesPrefixProvider implements NacosPropertiesPrefixProvider {\n\n\t@Override\n\tpublic String getPrefix() {\n\t\treturn \"spring.cloud.nacos\";\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceLocator.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.client;\n\nimport java.util.List;\n\nimport com.alibaba.cloud.commons.lang.StringUtils;\nimport com.alibaba.cloud.nacos.NacosConfigManager;\nimport com.alibaba.cloud.nacos.NacosConfigProperties;\nimport com.alibaba.cloud.nacos.NacosPropertySourceRepository;\nimport com.alibaba.cloud.nacos.parser.NacosDataParserHandler;\nimport com.alibaba.cloud.nacos.refresh.NacosContextRefresher;\nimport com.alibaba.nacos.api.config.ConfigService;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.cloud.bootstrap.config.PropertySourceLocator;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.core.env.CompositePropertySource;\nimport org.springframework.core.env.Environment;\nimport org.springframework.core.env.PropertySource;\n\n/**\n * @author xiaojing\n * @author pbting\n */\n@Order(0)\n@Deprecated\npublic class NacosPropertySourceLocator implements PropertySourceLocator {\n\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(NacosPropertySourceLocator.class);\n\n\tprivate static final String NACOS_PROPERTY_SOURCE_NAME = \"NACOS\";\n\n\tprivate static final String SEP1 = \"-\";\n\n\tprivate static final String DOT = \".\";\n\n\tprivate NacosPropertySourceBuilder nacosPropertySourceBuilder;\n\n\tprivate NacosConfigProperties nacosConfigProperties;\n\n\tprivate NacosConfigManager nacosConfigManager;\n\n\t/**\n\t * recommend to use\n\t * {@link NacosPropertySourceLocator#NacosPropertySourceLocator(com.alibaba.cloud.nacos.NacosConfigManager)}.\n\t * @param nacosConfigProperties nacosConfigProperties\n\t */\n\t@Deprecated\n\tpublic NacosPropertySourceLocator(NacosConfigProperties nacosConfigProperties) {\n\t\tthis.nacosConfigProperties = nacosConfigProperties;\n\t}\n\n\tpublic NacosPropertySourceLocator(NacosConfigManager nacosConfigManager) {\n\t\tthis.nacosConfigManager = nacosConfigManager;\n\t\tthis.nacosConfigProperties = nacosConfigManager.getNacosConfigProperties();\n\t}\n\n\t@Override\n\tpublic PropertySource<?> locate(Environment env) {\n\t\tConfigService configService = nacosConfigManager.getConfigService();\n\n\t\tif (null == configService) {\n\t\t\tlog.warn(\"no instance of config service found, can't load config from nacos\");\n\t\t\treturn null;\n\t\t}\n\t\tlong timeout = nacosConfigProperties.getTimeout();\n\t\tnacosPropertySourceBuilder = new NacosPropertySourceBuilder(configService,\n\t\t\t\ttimeout);\n\t\tString name = nacosConfigProperties.getName();\n\n\t\tString dataIdPrefix = nacosConfigProperties.getPrefix();\n\t\tif (StringUtils.isEmpty(dataIdPrefix)) {\n\t\t\tdataIdPrefix = name;\n\t\t}\n\n\t\tif (StringUtils.isEmpty(dataIdPrefix)) {\n\t\t\tdataIdPrefix = env.getProperty(\"spring.application.name\");\n\t\t}\n\n\t\tCompositePropertySource composite = new CompositePropertySource(\n\t\t\t\tNACOS_PROPERTY_SOURCE_NAME);\n\n\t\tloadApplicationConfiguration(composite, dataIdPrefix, nacosConfigProperties, env);\n\t\treturn composite;\n\t}\n\n\t/**\n\t * load configuration of application.\n\t */\n\tprivate void loadApplicationConfiguration(\n\t\t\tCompositePropertySource compositePropertySource, String dataIdPrefix,\n\t\t\tNacosConfigProperties properties, Environment environment) {\n\t\tString fileExtension = properties.getFileExtension();\n\t\tString nacosGroup = properties.getGroup();\n\t\t// load directly once by default\n\t\tloadNacosDataIfPresent(compositePropertySource, dataIdPrefix, nacosGroup,\n\t\t\t\tfileExtension, true);\n\t\t// load with suffix, which have a higher priority than the default\n\t\tloadNacosDataIfPresent(compositePropertySource,\n\t\t\t\tdataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension, true);\n\t\t// Loaded with profile, which have a higher priority than the suffix\n\t\tfor (String profile : environment.getActiveProfiles()) {\n\t\t\tString dataId = dataIdPrefix + SEP1 + profile + DOT + fileExtension;\n\t\t\tloadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup,\n\t\t\t\t\tfileExtension, true);\n\t\t}\n\n\t}\n\n\tprivate void loadNacosConfiguration(final CompositePropertySource composite,\n\t\t\tList<NacosConfigProperties.Config> configs) {\n\t\tfor (NacosConfigProperties.Config config : configs) {\n\t\t\tloadNacosDataIfPresent(composite, config.getDataId(), config.getGroup(),\n\t\t\t\t\tNacosDataParserHandler.getInstance()\n\t\t\t\t\t\t\t.getFileExtension(config.getDataId()),\n\t\t\t\t\tconfig.isRefresh());\n\t\t}\n\t}\n\n\tprivate void checkConfiguration(List<NacosConfigProperties.Config> configs,\n\t\t\tString tips) {\n\t\tfor (int i = 0; i < configs.size(); i++) {\n\t\t\tString dataId = configs.get(i).getDataId();\n\t\t\tif (dataId == null || dataId.trim().length() == 0) {\n\t\t\t\tthrow new IllegalStateException(String.format(\n\t\t\t\t\t\t\"the [ spring.cloud.nacos.config.%s[%s] ] must give a dataId\",\n\t\t\t\t\t\ttips, i));\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void loadNacosDataIfPresent(final CompositePropertySource composite,\n\t\t\tfinal String dataId, final String group, String fileExtension,\n\t\t\tboolean isRefreshable) {\n\t\tif (null == dataId || dataId.trim().length() < 1) {\n\t\t\treturn;\n\t\t}\n\t\tif (null == group || group.trim().length() < 1) {\n\t\t\treturn;\n\t\t}\n\t\tNacosPropertySource propertySource = this.loadNacosPropertySource(dataId, group,\n\t\t\t\tfileExtension, isRefreshable);\n\t\tthis.addFirstPropertySource(composite, propertySource, false);\n\t}\n\n\tprivate NacosPropertySource loadNacosPropertySource(final String dataId,\n\t\t\tfinal String group, String fileExtension, boolean isRefreshable) {\n\t\tif (NacosContextRefresher.getRefreshCount() != 0) {\n\t\t\tif (!isRefreshable) {\n\t\t\t\treturn NacosPropertySourceRepository.getNacosPropertySource(dataId,\n\t\t\t\t\t\tgroup);\n\t\t\t}\n\t\t}\n\t\treturn nacosPropertySourceBuilder.build(dataId, group, fileExtension,\n\t\t\t\tisRefreshable);\n\t}\n\n\t/**\n\t * Add the nacos configuration to the first place and maybe ignore the empty\n\t * configuration.\n\t */\n\tprivate void addFirstPropertySource(final CompositePropertySource composite,\n\t\t\tNacosPropertySource nacosPropertySource, boolean ignoreEmpty) {\n\t\tif (null == nacosPropertySource || null == composite) {\n\t\t\treturn;\n\t\t}\n\t\tif (ignoreEmpty && nacosPropertySource.getSource().isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\tcomposite.addFirstPropertySource(nacosPropertySource);\n\t}\n\n\tpublic void setNacosConfigManager(NacosConfigManager nacosConfigManager) {\n\t\tthis.nacosConfigManager = nacosConfigManager;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataMissingEnvironmentPostProcessor.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.configdata;\n\nimport com.alibaba.cloud.nacos.NacosPropertiesPrefixer;\n\nimport org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor;\nimport org.springframework.boot.diagnostics.AbstractFailureAnalyzer;\nimport org.springframework.boot.diagnostics.FailureAnalysis;\nimport org.springframework.cloud.commons.ConfigDataMissingEnvironmentPostProcessor;\nimport org.springframework.cloud.util.PropertyUtils;\nimport org.springframework.core.env.Environment;\n\nimport static com.alibaba.cloud.nacos.configdata.NacosConfigDataLocationResolver.PREFIX;\n\n/**\n *\n * @author freeman\n * @since 2021.0.1.0\n */\npublic class NacosConfigDataMissingEnvironmentPostProcessor\n\t\textends ConfigDataMissingEnvironmentPostProcessor {\n\n\t/**\n\t * after {@link ConfigDataEnvironmentPostProcessor}.\n\t */\n\tpublic static final int ORDER = ConfigDataEnvironmentPostProcessor.ORDER + 1000;\n\n\t@Override\n\tpublic int getOrder() {\n\t\treturn ORDER;\n\t}\n\n\t@Override\n\tprotected boolean shouldProcessEnvironment(Environment environment) {\n\t\t// don't run if using bootstrap or legacy processing\n\t\tif (PropertyUtils.bootstrapEnabled(environment) || PropertyUtils.useLegacyProcessing(environment)) {\n\t\t\treturn false;\n\t\t}\n\t\tString prefix = NacosPropertiesPrefixer.getPrefix(environment);\n\t\tString configPrefix = prefix + \".config\";\n\n\t\tboolean configEnabled = environment.getProperty(\n\t\t\t\tconfigPrefix + \".enabled\", Boolean.class, true);\n\t\tboolean importCheckEnabled = environment.getProperty(\n\t\t\t\tconfigPrefix + \".import-check.enabled\", Boolean.class,\n\t\t\t\ttrue);\n\t\treturn configEnabled && importCheckEnabled;\n\t}\n\n\t@Override\n\tprotected String getPrefix() {\n\t\treturn PREFIX;\n\t}\n\n\tstatic class ImportExceptionFailureAnalyzer\n\t\t\textends AbstractFailureAnalyzer<ImportException> {\n\n\t\t@Override\n\t\tprotected FailureAnalysis analyze(Throwable rootFailure, ImportException cause) {\n\t\t\tString description;\n\t\t\tif (cause.missingPrefix) {\n\t\t\t\tdescription = \"The spring.config.import property is missing a \" + PREFIX\n\t\t\t\t\t\t+ \" entry\";\n\t\t\t}\n\t\t\telse {\n\t\t\t\tdescription = \"No spring.config.import property has been defined\";\n\t\t\t}\n\t\t\tString action = \"Add a spring.config.import=nacos: property to your configuration.\\n\"\n\t\t\t\t\t+ \"\\tIf configuration is not required add spring.config.import=optional:nacos: instead.\\n\"\n\t\t\t\t\t+ \"\\tTo disable this check, set spring.cloud.nacos.config.import-check.enabled=false.\";\n\t\t\treturn new FailureAnalysis(description, action, cause);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/configdata/NacosConfigRefreshEventListener.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.configdata;\n\nimport com.alibaba.cloud.nacos.refresh.NacosConfigRefreshEvent;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.cloud.endpoint.event.RefreshEvent;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.context.ApplicationEvent;\nimport org.springframework.context.event.SmartApplicationListener;\n\n/**\n *\n * @author shiyiyue\n * @since 2024.10.17\n */\npublic class NacosConfigRefreshEventListener implements SmartApplicationListener, ApplicationContextAware {\n\n\tprivate final static Logger log = LoggerFactory.getLogger(NacosConfigRefreshEventListener.class);\n\n\tprivate ApplicationContext applicationContext;\n\n\t@Override\n\tpublic boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {\n\t\treturn NacosConfigRefreshEvent.class.isAssignableFrom(eventType);\n\t}\n\n\t@Override\n\tpublic void setApplicationContext(ApplicationContext applicationContext) {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n\t@Override\n\tpublic void onApplicationEvent(ApplicationEvent event) {\n\t\tapplicationContext.publishEvent(new RefreshEvent(event.getSource(), null, \"Refresh Nacos config\"));\n\t\tif (log.isDebugEnabled()) {\n\t\t\tlog.debug(String.format(\"Refresh Nacos config group=%s,dataId=%s\", ((NacosConfigRefreshEvent) event).getGroup(), ((NacosConfigRefreshEvent) event).getDataId()));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/refresh/RefreshBehavior.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.refresh;\n\nimport org.springframework.boot.context.properties.ConfigurationPropertiesBean;\n\n/**\n * Refresh behavior.\n *\n * @author freeman\n * @since 2021.0.1.1\n */\npublic enum RefreshBehavior {\n\t/**\n\t * Refresh all {@link ConfigurationPropertiesBean}s.\n\t */\n\tALL_BEANS,\n\t/**\n\t * Refresh specific {@link ConfigurationPropertiesBean} base on change key.\n\t */\n\tSPECIFIC_BEAN,\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/refresh/SmartConfigurationPropertiesRebinder.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.refresh;\n\nimport java.lang.reflect.Field;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.Set;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.boot.context.properties.ConfigurationPropertiesBean;\nimport org.springframework.cloud.context.environment.EnvironmentChangeEvent;\nimport org.springframework.cloud.context.properties.ConfigurationPropertiesBeans;\nimport org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.core.annotation.AnnotationUtils;\nimport org.springframework.util.ReflectionUtils;\n\n/**\n * Extend {@link ConfigurationPropertiesRebinder}.\n * <p>\n * Spring team doesn't seem to support single {@link ConfigurationPropertiesBean} refresh.\n * <p>\n * SmartConfigurationPropertiesRebinder can refresh specific\n * {@link ConfigurationPropertiesBean} base on the change keys.\n * <p>\n * <strong> NOTE: We still use Spring's default behavior (full refresh) as default\n * behavior, This feature can be considered an advanced feature, it may not be as stable\n * as the default behavior. </strong>\n *\n * @author freeman\n * @since 2021.0.1.1\n */\npublic class SmartConfigurationPropertiesRebinder\n\t\textends ConfigurationPropertiesRebinder {\n\n\tprivate Map<String, ConfigurationPropertiesBean> beanMap;\n\n\tprivate ApplicationContext applicationContext;\n\n\tprivate RefreshBehavior refreshBehavior;\n\n\tpublic SmartConfigurationPropertiesRebinder(ConfigurationPropertiesBeans beans) {\n\t\tsuper(beans);\n\t\tfillBeanMap(beans);\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tprivate void fillBeanMap(ConfigurationPropertiesBeans beans) {\n\t\tthis.beanMap = new HashMap<>();\n\t\tField field = ReflectionUtils.findField(beans.getClass(), \"beans\");\n\t\tif (field != null) {\n\t\t\tfield.setAccessible(true);\n\t\t\tthis.beanMap.putAll((Map<String, ConfigurationPropertiesBean>) Optional\n\t\t\t\t\t.ofNullable(ReflectionUtils.getField(field, beans))\n\t\t\t\t\t.orElse(Collections.emptyMap()));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setApplicationContext(ApplicationContext applicationContext)\n\t\t\tthrows BeansException {\n\t\tsuper.setApplicationContext(applicationContext);\n\t\tthis.applicationContext = applicationContext;\n\t\tthis.refreshBehavior = this.applicationContext.getEnvironment().getProperty(\n\t\t\t\t\"spring.cloud.nacos.config.refresh-behavior\", RefreshBehavior.class,\n\t\t\t\tRefreshBehavior.ALL_BEANS);\n\t}\n\n\t@Override\n\tpublic void onApplicationEvent(EnvironmentChangeEvent event) {\n\t\tif (this.applicationContext.equals(event.getSource())\n\t\t\t\t// Backwards compatible\n\t\t\t\t|| event.getKeys().equals(event.getSource())) {\n\t\t\tswitch (refreshBehavior) {\n\t\t\tcase SPECIFIC_BEAN -> rebindSpecificBean(event);\n\t\t\tdefault -> rebind();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void rebindSpecificBean(EnvironmentChangeEvent event) {\n\t\tSet<String> refreshedSet = new HashSet<>();\n\t\tbeanMap.forEach((name, bean) -> event.getKeys().forEach(changeKey -> {\n\t\t\tString prefix = AnnotationUtils.getValue(bean.getAnnotation()).toString();\n\t\t\t// prevent multiple refresh one ConfigurationPropertiesBean.\n\t\t\tif (changeKey.startsWith(prefix) && refreshedSet.add(name)) {\n\t\t\t\trebind(name);\n\t\t\t}\n\t\t}));\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/refresh/condition/ConditionalOnNonDefaultBehavior.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.refresh.condition;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\nimport com.alibaba.cloud.nacos.refresh.RefreshBehavior;\n\nimport org.springframework.context.annotation.Conditional;\n\n/**\n * Condition on {@link RefreshBehavior} is <strong>NOT</strong> default.\n *\n * @author freeman\n * @since 2021.0.1.1\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ ElementType.TYPE, ElementType.METHOD })\n@Documented\n@Conditional(com.alibaba.cloud.nacos.refresh.condition.NonDefaultBehaviorCondition.class)\npublic @interface ConditionalOnNonDefaultBehavior {\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/refresh/condition/NonDefaultBehaviorCondition.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.refresh.condition;\n\nimport com.alibaba.cloud.nacos.NacosPropertiesPrefixer;\nimport com.alibaba.cloud.nacos.refresh.RefreshBehavior;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionOutcome;\nimport org.springframework.boot.autoconfigure.condition.SpringBootCondition;\nimport org.springframework.context.annotation.ConditionContext;\nimport org.springframework.core.type.AnnotatedTypeMetadata;\n\n/**\n * @author freeman\n * @since 2021.0.1.1\n */\npublic class NonDefaultBehaviorCondition extends SpringBootCondition {\n\n\tprivate static final RefreshBehavior DEFAULT_REFRESH_BEHAVIOR = RefreshBehavior.ALL_BEANS;\n\n\t@Override\n\tpublic ConditionOutcome getMatchOutcome(ConditionContext context,\n\t\t\tAnnotatedTypeMetadata metadata) {\n\t\tString prefix = NacosPropertiesPrefixer.getPrefix(context.getEnvironment());\n\t\tRefreshBehavior behavior = context.getEnvironment().getProperty(\n\t\t\t\tprefix + \".config.refresh-behavior\", RefreshBehavior.class,\n\t\t\t\tDEFAULT_REFRESH_BEHAVIOR);\n\t\tif (DEFAULT_REFRESH_BEHAVIOR == behavior) {\n\t\t\treturn ConditionOutcome.noMatch(\"no matched\");\n\t\t}\n\t\treturn ConditionOutcome.match(\"matched\");\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json",
    "content": "{\n  \"properties\": [\n    {\n      \"name\": \"spring.cloud.nacos.server-addr\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"127.0.0.1:8848\",\n      \"description\": \"nacos server address.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.server-addr\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"${spring.cloud.nacos.server-addr}\",\n      \"description\": \"nacos config server address.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.encode\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"UTF-8\",\n      \"description\": \"default encode for nacos config content.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.prefix\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"${spring.application.name}\",\n      \"description\": \"the prefix of dataId, nacos config data meta info. dataId = prefix + '-' + ${spring.active.profile} + `.` + ${spring.cloud.nacos.config.file-extension}.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.file-extension\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"properties\",\n      \"description\": \"the suffix of nacos config dataId, also the file extension of config content, only support properties now.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.shared-dataids\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"the dataids for configurable multiple shared configurations , multiple separated by commas .\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.shared-configs\",\n      \"type\": \"java.util.List\",\n      \"description\": \"a set of shared configurations .e.g: spring.cloud.nacos.config.shared-configs[0]=xxx .\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.refreshable-dataids\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"refreshable dataids , multiple separated by commas .Not providing support,the need to refresh is specified by the respective refresh configuration.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.ext-config\",\n      \"type\": \"java.util.List\",\n      \"description\": \"a set of extended configurations .\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.extension-configs\",\n      \"type\": \"java.util.List\",\n      \"description\": \"a set of extensional configurations .e.g: spring.cloud.nacos.config.extension-configs[0]=xxx .\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.refresh-enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": true,\n      \"description\": \"the master switch for refresh configuration, it default opened(true).\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": true,\n      \"description\": \"enable nacos config or not.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.username\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"${spring.cloud.nacos.username}\",\n      \"description\": \"nacos config service's userName to authenticate.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.import-check.enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": true,\n      \"description\": \"Whether to enable import-check.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.password\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"${spring.cloud.nacos.password}\",\n      \"description\": \"nacos config service's password to authenticate.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.username\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"nacos userName to authenticate.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.password\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"nacos password to authenticate.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.refresh-behavior\",\n      \"type\": \"com.alibaba.cloud.nacos.refresh.RefreshBehavior\",\n      \"defaultValue\": \"all_beans\",\n      \"description\": \"ConfigurationPropertiesBean refresh behavior.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.preference\",\n      \"type\": \"com.alibaba.cloud.nacos.configdata.ConfigPreference\",\n      \"defaultValue\": \"local\",\n      \"description\": \"Config preference.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.group\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"DEFAULT_GROUP\",\n      \"description\": \"Config group，group is config data meta info.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.timeout\",\n      \"type\": \"java.lang.Integer\",\n      \"defaultValue\": \"3000\",\n      \"description\": \"Config timeout.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.max-retry\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"\",\n      \"description\": \"Config maximum number of tolerable server reconnection errors.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.config-long-poll-timeout\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"\",\n      \"description\": \"Config long poll timeout.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.config-retry-time\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"\",\n      \"description\": \"Config failure retry time.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.enable-remote-sync-config\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": \"false\",\n      \"description\": \"Config enable remote sync config.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.endpoint\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"\",\n      \"description\": \"Config endpoint.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.namespace\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"\",\n      \"description\": \"Config namespace.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.access-key\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"\",\n      \"description\": \"Config access key for namespace.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.secret-key\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"\",\n      \"description\": \"Config secret key for namespace.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.ram-role-name\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"\",\n      \"description\": \"Config ole name for aliyun ram.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.context-path\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"\",\n      \"description\": \"Config context path.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.config.cluster-name\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"\",\n      \"description\": \"Config cluster name.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.name\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"\",\n      \"description\": \"Config dataId name.\"\n    }\n  ]\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/resources/META-INF/services/com.alibaba.cloud.nacos.NacosPropertiesPrefixProvider",
    "content": "com.alibaba.cloud.nacos.SpringCloudNacosPropertiesPrefixProvider"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports",
    "content": "com.alibaba.cloud.nacos.NacosConfigSpringCloudAutoConfiguration\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/resources/META-INF/spring.factories",
    "content": "org.springframework.boot.diagnostics.FailureAnalyzer=\\\ncom.alibaba.cloud.nacos.configdata.NacosConfigDataMissingEnvironmentPostProcessor.ImportExceptionFailureAnalyzer\norg.springframework.boot.EnvironmentPostProcessor=\\\ncom.alibaba.cloud.nacos.configdata.NacosConfigDataMissingEnvironmentPostProcessor\n\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/SmartConfigurationPropertiesRebinderIntegrationTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\nimport com.alibaba.cloud.nacos.refresh.RefreshBehavior;\nimport com.alibaba.cloud.nacos.refresh.SmartConfigurationPropertiesRebinder;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.boot.WebApplicationType;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder;\nimport org.springframework.context.ConfigurableApplicationContext;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * {@link SmartConfigurationPropertiesRebinder} tester.\n *\n * @author freeman\n */\npublic class SmartConfigurationPropertiesRebinderIntegrationTest {\n\n\tConfigurableApplicationContext context;\n\n\t@Test\n\tpublic void testUsingSmartConfigurationPropertiesRebinder_whenBehaviorIsNotDefault() {\n\t\tcontext = new SpringApplicationBuilder(RebinderConfiguration.class)\n\t\t\t\t.web(WebApplicationType.NONE)\n\t\t\t\t.properties(\"spring.cloud.nacos.config.refresh-behavior=specific_bean\")\n\t\t\t\t.properties(\"spring.cloud.nacos.server-addr=123.123.123.123:8848\")\n\t\t\t\t.properties(\"spring.cloud.nacos.config.import-check.enabled=false\")\n\t\t\t\t.properties(\"spring.config.import=nacos:test.properties\").run();\n\n\t\tConfigurationPropertiesRebinder rebinder = context\n\t\t\t\t.getBean(ConfigurationPropertiesRebinder.class);\n\n\t\tassertThat(rebinder.getClass())\n\t\t\t\t.isEqualTo(SmartConfigurationPropertiesRebinder.class);\n\n\t\tRefreshBehavior refreshBehavior = (RefreshBehavior) ReflectionTestUtils\n\t\t\t\t.getField(rebinder, \"refreshBehavior\");\n\t\tassertThat(refreshBehavior).isEqualTo(RefreshBehavior.SPECIFIC_BEAN);\n\t}\n\n\t@Test\n\tpublic void testUsingConfigurationPropertiesRebinder_whenBehaviorIsDefault() {\n\t\tcontext = new SpringApplicationBuilder(RebinderConfiguration.class)\n\t\t\t\t.web(WebApplicationType.NONE)\n\t\t\t\t.properties(\"spring.cloud.nacos.server-addr=123.123.123.123:8848\")\n\t\t\t\t.properties(\"spring.cloud.nacos.config.import-check.enabled=false\")\n\t\t\t\t.properties(\"spring.config.import=nacos:test.properties\").run();\n\n\t\tConfigurationPropertiesRebinder rebinder = context\n\t\t\t\t.getBean(ConfigurationPropertiesRebinder.class);\n\n\t\tassertThat(rebinder.getClass()).isEqualTo(ConfigurationPropertiesRebinder.class);\n\t}\n\n\t@Configuration\n\t@ImportAutoConfiguration({ NacosConfigSpringCloudAutoConfiguration.class })\n\t@EnableAutoConfiguration\n\tpublic static class RebinderConfiguration {\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataMissingEnvironmentPostProcessorTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.configdata;\n\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.mock.env.MockEnvironment;\n\n/**\n *\n * @author Ryan Baxter\n * @author freeman\n */\nclass NacosConfigDataMissingEnvironmentPostProcessorTest {\n\n\t@Test\n\tvoid noSpringConfigImport() {\n\t\tMockEnvironment environment = new MockEnvironment();\n\t\tSpringApplication app = Mockito.mock(SpringApplication.class);\n\t\tNacosConfigDataMissingEnvironmentPostProcessor processor = new NacosConfigDataMissingEnvironmentPostProcessor();\n\t\tAssertions.assertThatThrownBy(() -> processor.postProcessEnvironment(environment, app))\n\t\t\t\t.isInstanceOf(\n\t\t\t\t\t\tNacosConfigDataMissingEnvironmentPostProcessor.ImportException.class);\n\t}\n\n\t@Test\n\tvoid boostrap() {\n\t\tMockEnvironment environment = new MockEnvironment();\n\t\tenvironment.setProperty(\"spring.cloud.bootstrap.enabled\", \"true\");\n\t\tSpringApplication app = Mockito.mock(SpringApplication.class);\n\t\tNacosConfigDataMissingEnvironmentPostProcessor processor = new NacosConfigDataMissingEnvironmentPostProcessor();\n\t\tAssertions.assertThatCode(() -> processor.postProcessEnvironment(environment, app))\n\t\t\t\t.doesNotThrowAnyException();\n\t}\n\n\t@Test\n\tvoid legacy() {\n\t\tMockEnvironment environment = new MockEnvironment();\n\t\tenvironment.setProperty(\"spring.config.use-legacy-processing\", \"true\");\n\t\tSpringApplication app = Mockito.mock(SpringApplication.class);\n\t\tNacosConfigDataMissingEnvironmentPostProcessor processor = new NacosConfigDataMissingEnvironmentPostProcessor();\n\t\tAssertions.assertThatCode(() -> processor.postProcessEnvironment(environment, app))\n\t\t\t\t.doesNotThrowAnyException();\n\t}\n\n\t@Test\n\tvoid configNotEnabled() {\n\t\tMockEnvironment environment = new MockEnvironment();\n\t\tenvironment.setProperty(\"spring.cloud.nacos.config.enabled\", \"false\");\n\t\tSpringApplication app = Mockito.mock(SpringApplication.class);\n\t\tNacosConfigDataMissingEnvironmentPostProcessor processor = new NacosConfigDataMissingEnvironmentPostProcessor();\n\t\tAssertions.assertThatCode(() -> processor.postProcessEnvironment(environment, app))\n\t\t\t\t.doesNotThrowAnyException();\n\t}\n\n\t@Test\n\tvoid importCheckNotEnabled() {\n\t\tMockEnvironment environment = new MockEnvironment();\n\t\tenvironment.setProperty(\"spring.cloud.nacos.config.import-check.enabled\",\n\t\t\t\t\"false\");\n\t\tSpringApplication app = Mockito.mock(SpringApplication.class);\n\t\tNacosConfigDataMissingEnvironmentPostProcessor processor = new NacosConfigDataMissingEnvironmentPostProcessor();\n\t\tAssertions.assertThatCode(() -> processor.postProcessEnvironment(environment, app))\n\t\t\t\t.doesNotThrowAnyException();\n\t}\n\n\t@Test\n\tvoid importSinglePropertySource() {\n\t\tMockEnvironment environment = new MockEnvironment();\n\t\tenvironment.setProperty(\"spring.config.import\", \"nacos:test.yml\");\n\t\tSpringApplication app = Mockito.mock(SpringApplication.class);\n\t\tNacosConfigDataMissingEnvironmentPostProcessor processor = new NacosConfigDataMissingEnvironmentPostProcessor();\n\t\tAssertions.assertThatCode(() -> processor.postProcessEnvironment(environment, app))\n\t\t\t\t.doesNotThrowAnyException();\n\t}\n\n\t@Test\n\tvoid importMultiplePropertySource() {\n\t\tMockEnvironment environment = new MockEnvironment();\n\t\tenvironment.setProperty(\"spring.config.import\", \"nacos:test.yml\");\n\t\tSpringApplication app = Mockito.mock(SpringApplication.class);\n\t\tNacosConfigDataMissingEnvironmentPostProcessor processor = new NacosConfigDataMissingEnvironmentPostProcessor();\n\t\tAssertions.assertThatCode(() -> processor.postProcessEnvironment(environment, app))\n\t\t\t\t.doesNotThrowAnyException();\n\t}\n\n\t@Test\n\tvoid importMultiplePropertySourceAsList() {\n\t\tMockEnvironment environment = new MockEnvironment();\n\t\tenvironment.setProperty(\"spring.config.import[0]\", \"nacos:test.yml\");\n\t\tenvironment.setProperty(\"spring.config.import[1]\", \"file:./app.properties\");\n\t\tSpringApplication app = Mockito.mock(SpringApplication.class);\n\t\tNacosConfigDataMissingEnvironmentPostProcessor processor = new NacosConfigDataMissingEnvironmentPostProcessor();\n\t\tAssertions.assertThatCode(() -> processor.postProcessEnvironment(environment, app))\n\t\t\t\t.doesNotThrowAnyException();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-starters</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n    <name>Spring Cloud Starter Alibaba Nacos Discovery</name>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-health</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-alibaba-commons</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-actuator</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-actuator-autoconfigure</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-configuration-processor</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-webflux</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-client</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>com.alibaba.nacos</groupId>\n                    <artifactId>nacos-logback-adapter-12</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-commons</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-context</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-config-client</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-config-server</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-loadbalancer</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>io.projectreactor</groupId>\n            <artifactId>reactor-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n    </dependencies>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/ConditionalOnNacosDiscoveryEnabled.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\n\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ ElementType.TYPE, ElementType.METHOD })\n@ConditionalOnProperty(value = \"spring.cloud.nacos.discovery.enabled\",\n\t\tmatchIfMissing = true)\npublic @interface ConditionalOnNacosDiscoveryEnabled {\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\nimport java.net.Inet4Address;\nimport java.net.Inet6Address;\nimport java.net.InetAddress;\nimport java.net.NetworkInterface;\nimport java.util.Enumeration;\nimport java.util.HashMap;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Properties;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport com.alibaba.cloud.commons.context.support.PropertySourcesUtils;\nimport com.alibaba.cloud.commons.lang.StringUtils;\nimport com.alibaba.cloud.nacos.event.NacosDiscoveryInfoChangedEvent;\nimport com.alibaba.cloud.nacos.util.InetIPv6Utils;\nimport com.alibaba.nacos.api.naming.NamingService;\nimport com.alibaba.nacos.api.naming.PreservedMetadataKeys;\nimport com.alibaba.nacos.client.naming.utils.UtilAndComs;\nimport jakarta.annotation.PostConstruct;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.cloud.commons.util.InetUtils;\nimport org.springframework.context.ApplicationEventPublisher;\nimport org.springframework.core.env.ConfigurableEnvironment;\nimport org.springframework.core.env.Environment;\n\nimport static com.alibaba.nacos.api.PropertyKeyConst.ACCESS_KEY;\nimport static com.alibaba.nacos.api.PropertyKeyConst.ENDPOINT;\nimport static com.alibaba.nacos.api.PropertyKeyConst.ENDPOINT_PORT;\nimport static com.alibaba.nacos.api.PropertyKeyConst.NAMESPACE;\nimport static com.alibaba.nacos.api.PropertyKeyConst.NAMING_LOAD_CACHE_AT_START;\nimport static com.alibaba.nacos.api.PropertyKeyConst.PASSWORD;\nimport static com.alibaba.nacos.api.PropertyKeyConst.SECRET_KEY;\nimport static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR;\nimport static com.alibaba.nacos.api.PropertyKeyConst.USERNAME;\n\n/**\n * @author dungu.zpf\n * @author xiaojing\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n * @author <a href=\"mailto:lyuzb@lyuzb.com\">lyuzb</a>\n * @author <a href=\"mailto:78552423@qq.com\">eshun</a>\n * @author freeman\n */\n@ConfigurationProperties(\"spring.cloud.nacos.discovery\")\npublic class NacosDiscoveryProperties {\n\n\t/**\n\t * Prefix of {@link NacosDiscoveryProperties}.\n\t */\n\tpublic static final String PREFIX = \"spring.cloud.nacos.discovery\";\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(NacosDiscoveryProperties.class);\n\tprivate static final Pattern PATTERN = Pattern.compile(\"-(\\\\w)\");\n\n\tprivate static final String IPV4 = \"IPv4\";\n\n\tprivate static final String IPV6 = \"IPv6\";\n\n\t/**\n\t * nacos discovery server address.\n\t */\n\tprivate String serverAddr;\n\n\t/**\n\t * the nacos authentication username.\n\t */\n\tprivate String username;\n\n\t/**\n\t * the nacos authentication password.\n\t */\n\tprivate String password;\n\n\t/**\n\t * the domain name of a service, through which the server address can be dynamically\n\t * obtained.\n\t */\n\tprivate String endpoint;\n\n\t/**\n\t * namespace, separation registry of different environments.\n\t */\n\tprivate String namespace;\n\n\t/**\n\t * watch delay,duration to pull new service from nacos server.\n\t */\n\tprivate long watchDelay = 30000;\n\n\t/**\n\t * nacos naming log file name.\n\t */\n\tprivate String logName;\n\n\t/**\n\t * service name to registry.\n\t */\n\t@Value(\"${spring.cloud.nacos.discovery.service:${spring.application.name:}}\")\n\tprivate String service;\n\n\t/**\n\t * weight for service instance, the larger the value, the larger the weight.\n\t */\n\tprivate float weight = 1;\n\n\t/**\n\t * cluster name for nacos .\n\t */\n\tprivate String clusterName;\n\n\t/**\n\t * group name for nacos.\n\t */\n\tprivate String group = \"DEFAULT_GROUP\";\n\n\t/**\n\t * naming load from local cache at application start. true is load.\n\t */\n\tprivate String namingLoadCacheAtStart = \"false\";\n\n\t/**\n\t * extra metadata to register.\n\t */\n\tprivate Map<String, String> metadata = new HashMap<>();\n\n\t/**\n\t * if you just want to subscribe, but don't want to register your service, set it to\n\t * false.\n\t */\n\tprivate boolean registerEnabled = true;\n\n\t/**\n\t * The ip address your want to register for your service instance, needn't to set it\n\t * if the auto detect ip works well.\n\t */\n\tprivate String ip;\n\n\t/**\n\t * which network interface's ip you want to register.\n\t */\n\tprivate String networkInterface = \"\";\n\n\t/**\n\t * choose IPv4 or IPv6,if you don't set it will choose IPv4.\n\t * When IPv6 is chosen but no IPv6 can be found, system will automatically find IPv4 to ensure there is an\n\t * available service address.\n\t */\n\tprivate String ipType;\n\n\t/**\n\t * The port your want to register for your service instance, needn't to set it if the\n\t * auto detect port works well.\n\t */\n\tprivate int port = -1;\n\n\t/**\n\t * whether your service is a https service.\n\t */\n\tprivate boolean secure = false;\n\n\t/**\n\t * access key for namespace.\n\t */\n\tprivate String accessKey;\n\n\t/**\n\t * secret key for namespace.\n\t */\n\tprivate String secretKey;\n\n\t/**\n\t * Heart beat interval. Time unit: millisecond.\n\t */\n\tprivate Integer heartBeatInterval;\n\n\t/**\n\t * Heart beat timeout. Time unit: millisecond.\n\t */\n\tprivate Integer heartBeatTimeout;\n\n\t/**\n\t * Ip delete timeout. Time unit: millisecond.\n\t */\n\tprivate Integer ipDeleteTimeout;\n\n\t/**\n\t * If instance is enabled to accept request. The default value is true.\n\t */\n\tprivate boolean instanceEnabled = true;\n\n\t/**\n\t * If instance is ephemeral.The default value is true.\n\t */\n\tprivate boolean ephemeral = true;\n\n\t/**\n\t * Whether to enable nacos failure tolerance. If enabled, nacos will return cached\n\t * values when exceptions occur.\n\t */\n\tprivate boolean failureToleranceEnabled;\n\n\t/**\n\t * Throw exceptions during service registration if true, otherwise, log error\n\t * (defaults to true).\n\t */\n\tprivate boolean failFast = true;\n\n\t/**\n\t * graceful shutdown wait time. Time unit: millisecond.\n\t * default is 10s\n\t * When the Springboot shutdown hook is executed, remove the Nacos service, wait for 10 seconds, and then Tomcat rejects the request\n\t */\n\tprivate Integer gracefulShutdownWaitTime = 10 * 1000;\n\n\t@Autowired\n\tprivate InetIPv6Utils inetIPv6Utils;\n\n\t@Autowired\n\tprivate InetUtils inetUtils;\n\n\t@Autowired\n\tprivate Environment environment;\n\n\t@Autowired\n\tprivate NacosServiceManager nacosServiceManager;\n\n\t@Autowired\n\tprivate ApplicationEventPublisher applicationEventPublisher;\n\n\t@PostConstruct\n\tpublic void init() throws Exception {\n\n\t\tmetadata.put(PreservedMetadataKeys.REGISTER_SOURCE, \"SPRING_CLOUD\");\n\t\tif (secure) {\n\t\t\tmetadata.put(\"secure\", \"true\");\n\t\t}\n\n\t\tserverAddr = Objects.toString(serverAddr, \"\");\n\t\tif (serverAddr.endsWith(\"/\")) {\n\t\t\tserverAddr = serverAddr.substring(0, serverAddr.length() - 1);\n\t\t}\n\t\tendpoint = Objects.toString(endpoint, \"\");\n\t\tnamespace = Objects.toString(namespace, \"\");\n\t\tlogName = Objects.toString(logName, \"\");\n\n\t\tif (StringUtils.isEmpty(ip)) {\n\t\t\t// traversing network interfaces if didn't specify an interface\n\t\t\tif (StringUtils.isEmpty(networkInterface)) {\n\t\t\t\tif (ipType == null) {\n\t\t\t\t\tip = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();\n\t\t\t\t\tString ipv6Addr = inetIPv6Utils.findIPv6Address();\n\t\t\t\t\tmetadata.put(IPV6, ipv6Addr);\n\t\t\t\t\tif (ipv6Addr != null) {\n\t\t\t\t\t\tmetadata.put(IPV6, ipv6Addr);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (IPV4.equalsIgnoreCase(ipType)) {\n\t\t\t\t\tip = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();\n\t\t\t\t}\n\t\t\t\telse if (IPV6.equalsIgnoreCase(ipType)) {\n\t\t\t\t\tip = inetIPv6Utils.findIPv6Address();\n\t\t\t\t\tif (StringUtils.isEmpty(ip)) {\n\t\t\t\t\t\tlog.warn(\"There is no available IPv6 found. Spring Cloud Alibaba will automatically find IPv4.\");\n\t\t\t\t\t\tip = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\t\"please checking the type of IP \" + ipType);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tNetworkInterface netInterface = NetworkInterface\n\t\t\t\t\t\t.getByName(networkInterface);\n\t\t\t\tif (null == netInterface) {\n\t\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\t\"no such interface \" + networkInterface);\n\t\t\t\t}\n\n\t\t\t\tEnumeration<InetAddress> inetAddress = netInterface.getInetAddresses();\n\t\t\t\twhile (inetAddress.hasMoreElements()) {\n\t\t\t\t\tInetAddress currentAddress = inetAddress.nextElement();\n\t\t\t\t\tif (currentAddress instanceof Inet4Address\n\t\t\t\t\t\t\t|| currentAddress instanceof Inet6Address\n\t\t\t\t\t\t\t&& !currentAddress.isLoopbackAddress()) {\n\t\t\t\t\t\tip = currentAddress.getHostAddress();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (StringUtils.isEmpty(ip)) {\n\t\t\t\t\tthrow new RuntimeException(\"cannot find available ip from\"\n\t\t\t\t\t\t\t+ \" network interface \" + networkInterface);\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\n\t\tthis.overrideFromEnv(environment);\n\t\tif (nacosServiceManager.isNacosDiscoveryInfoChanged(this)) {\n\t\t\tapplicationEventPublisher\n\t\t\t\t\t.publishEvent(new NacosDiscoveryInfoChangedEvent(this));\n\t\t}\n\t\tnacosServiceManager.setNacosDiscoveryProperties(this);\n\t}\n\n\t/**\n\t * recommend to use {@link NacosServiceManager#getNamingService()}.\n\t * @return NamingService\n\t */\n\t@Deprecated\n\tpublic NamingService namingServiceInstance() {\n\t\treturn nacosServiceManager.getNamingService();\n\t}\n\n\tpublic String getEndpoint() {\n\t\treturn endpoint;\n\t}\n\n\tpublic void setEndpoint(String endpoint) {\n\t\tthis.endpoint = endpoint;\n\t}\n\n\tpublic String getNamespace() {\n\t\treturn namespace;\n\t}\n\n\tpublic void setNamespace(String namespace) {\n\t\tthis.namespace = namespace;\n\t}\n\n\tpublic String getLogName() {\n\t\treturn logName;\n\t}\n\n\tpublic void setLogName(String logName) {\n\t\tthis.logName = logName;\n\t}\n\n\tpublic void setInetUtils(InetUtils inetUtils) {\n\t\tthis.inetUtils = inetUtils;\n\t}\n\n\tpublic float getWeight() {\n\t\treturn weight;\n\t}\n\n\tpublic void setWeight(float weight) {\n\t\tthis.weight = weight;\n\t}\n\n\tpublic String getClusterName() {\n\t\treturn clusterName;\n\t}\n\n\tpublic void setClusterName(String clusterName) {\n\t\tthis.clusterName = clusterName;\n\t}\n\n\tpublic String getService() {\n\t\treturn service;\n\t}\n\n\tpublic void setService(String service) {\n\t\tthis.service = service;\n\t}\n\n\tpublic boolean isRegisterEnabled() {\n\t\treturn registerEnabled;\n\t}\n\n\tpublic void setRegisterEnabled(boolean registerEnabled) {\n\t\tthis.registerEnabled = registerEnabled;\n\t}\n\n\tpublic String getIp() {\n\t\treturn ip;\n\t}\n\n\tpublic void setIp(String ip) {\n\t\tthis.ip = ip;\n\t}\n\n\tpublic String getIpType() {\n\t\treturn ipType;\n\t}\n\n\tpublic void setIpType(String ipType) {\n\t\tthis.ipType = ipType;\n\t}\n\n\tpublic String getNetworkInterface() {\n\t\treturn networkInterface;\n\t}\n\n\tpublic void setNetworkInterface(String networkInterface) {\n\t\tthis.networkInterface = networkInterface;\n\t}\n\n\tpublic int getPort() {\n\t\treturn port;\n\t}\n\n\tpublic void setPort(int port) {\n\t\tthis.port = port;\n\t}\n\n\tpublic boolean isSecure() {\n\t\treturn secure;\n\t}\n\n\tpublic void setSecure(boolean secure) {\n\t\tthis.secure = secure;\n\t}\n\n\tpublic Map<String, String> getMetadata() {\n\t\treturn metadata;\n\t}\n\n\tpublic void setMetadata(Map<String, String> metadata) {\n\t\tthis.metadata = metadata;\n\t}\n\n\tpublic String getServerAddr() {\n\t\treturn serverAddr;\n\t}\n\n\tpublic void setServerAddr(String serverAddr) {\n\t\tthis.serverAddr = serverAddr;\n\t}\n\n\tpublic String getAccessKey() {\n\t\treturn accessKey;\n\t}\n\n\tpublic void setAccessKey(String accessKey) {\n\t\tthis.accessKey = accessKey;\n\t}\n\n\tpublic String getSecretKey() {\n\t\treturn secretKey;\n\t}\n\n\tpublic void setSecretKey(String secretKey) {\n\t\tthis.secretKey = secretKey;\n\t}\n\n\tpublic Integer getHeartBeatInterval() {\n\t\treturn heartBeatInterval;\n\t}\n\n\tpublic void setHeartBeatInterval(Integer heartBeatInterval) {\n\t\tthis.heartBeatInterval = heartBeatInterval;\n\t}\n\n\tpublic Integer getHeartBeatTimeout() {\n\t\treturn heartBeatTimeout;\n\t}\n\n\tpublic void setHeartBeatTimeout(Integer heartBeatTimeout) {\n\t\tthis.heartBeatTimeout = heartBeatTimeout;\n\t}\n\n\tpublic Integer getIpDeleteTimeout() {\n\t\treturn ipDeleteTimeout;\n\t}\n\n\tpublic void setIpDeleteTimeout(Integer ipDeleteTimeout) {\n\t\tthis.ipDeleteTimeout = ipDeleteTimeout;\n\t}\n\n\tpublic String getNamingLoadCacheAtStart() {\n\t\treturn namingLoadCacheAtStart;\n\t}\n\n\tpublic void setNamingLoadCacheAtStart(String namingLoadCacheAtStart) {\n\t\tthis.namingLoadCacheAtStart = namingLoadCacheAtStart;\n\t}\n\n\tpublic long getWatchDelay() {\n\t\treturn watchDelay;\n\t}\n\n\tpublic void setWatchDelay(long watchDelay) {\n\t\tthis.watchDelay = watchDelay;\n\t}\n\n\tpublic String getGroup() {\n\t\treturn group;\n\t}\n\n\tpublic void setGroup(String group) {\n\t\tthis.group = group;\n\t}\n\n\tpublic String getUsername() {\n\t\treturn username;\n\t}\n\n\tpublic void setUsername(String username) {\n\t\tthis.username = username;\n\t}\n\n\tpublic String getPassword() {\n\t\treturn password;\n\t}\n\n\tpublic void setPassword(String password) {\n\t\tthis.password = password;\n\t}\n\n\tpublic boolean isInstanceEnabled() {\n\t\treturn instanceEnabled;\n\t}\n\n\tpublic void setInstanceEnabled(boolean instanceEnabled) {\n\t\tthis.instanceEnabled = instanceEnabled;\n\t}\n\n\tpublic boolean isEphemeral() {\n\t\treturn ephemeral;\n\t}\n\n\tpublic void setEphemeral(boolean ephemeral) {\n\t\tthis.ephemeral = ephemeral;\n\t}\n\n\tpublic boolean isFailureToleranceEnabled() {\n\t\treturn failureToleranceEnabled;\n\t}\n\n\tpublic void setFailureToleranceEnabled(boolean failureToleranceEnabled) {\n\t\tthis.failureToleranceEnabled = failureToleranceEnabled;\n\t}\n\n\tpublic boolean isFailFast() {\n\t\treturn failFast;\n\t}\n\n\tpublic void setFailFast(boolean failFast) {\n\t\tthis.failFast = failFast;\n\t}\n\n\tpublic Integer getGracefulShutdownWaitTime() {\n\t\treturn gracefulShutdownWaitTime;\n\t}\n\n\tpublic void setGracefulShutdownWaitTime(Integer gracefulShutdownWaitTime) {\n\t\tthis.gracefulShutdownWaitTime = gracefulShutdownWaitTime;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (this == o) {\n\t\t\treturn true;\n\t\t}\n\t\tif (o == null || getClass() != o.getClass()) {\n\t\t\treturn false;\n\t\t}\n\t\tNacosDiscoveryProperties that = (NacosDiscoveryProperties) o;\n\t\treturn watchDelay == that.watchDelay && Float.compare(that.weight, weight) == 0\n\t\t\t\t&& registerEnabled == that.registerEnabled && port == that.port\n\t\t\t\t&& secure == that.secure && instanceEnabled == that.instanceEnabled\n\t\t\t\t&& ephemeral == that.ephemeral\n\t\t\t\t&& failureToleranceEnabled == that.failureToleranceEnabled\n\t\t\t\t&& Objects.equals(serverAddr, that.serverAddr)\n\t\t\t\t&& Objects.equals(username, that.username)\n\t\t\t\t&& Objects.equals(password, that.password)\n\t\t\t\t&& Objects.equals(endpoint, that.endpoint)\n\t\t\t\t&& Objects.equals(namespace, that.namespace)\n\t\t\t\t&& Objects.equals(logName, that.logName)\n\t\t\t\t&& Objects.equals(service, that.service)\n\t\t\t\t&& Objects.equals(clusterName, that.clusterName)\n\t\t\t\t&& Objects.equals(group, that.group)\n\t\t\t\t&& Objects.equals(namingLoadCacheAtStart, that.namingLoadCacheAtStart)\n\t\t\t\t&& Objects.equals(metadata, that.metadata) && Objects.equals(ip, that.ip)\n\t\t\t\t&& Objects.equals(networkInterface, that.networkInterface)\n\t\t\t\t&& Objects.equals(accessKey, that.accessKey)\n\t\t\t\t&& Objects.equals(secretKey, that.secretKey)\n\t\t\t\t&& Objects.equals(heartBeatInterval, that.heartBeatInterval)\n\t\t\t\t&& Objects.equals(heartBeatTimeout, that.heartBeatTimeout)\n\t\t\t\t&& Objects.equals(failFast, that.failFast)\n\t\t\t\t&& Objects.equals(ipDeleteTimeout, that.ipDeleteTimeout);\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn Objects.hash(serverAddr, username, password, endpoint, namespace,\n\t\t\t\twatchDelay, logName, service, weight, clusterName, group,\n\t\t\t\tnamingLoadCacheAtStart, metadata, registerEnabled, ip, networkInterface,\n\t\t\t\tport, secure, accessKey, secretKey, heartBeatInterval, heartBeatTimeout,\n\t\t\t\tipDeleteTimeout, instanceEnabled, ephemeral, failureToleranceEnabled,\n\t\t\t\tfailFast);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"NacosDiscoveryProperties{\" + \"serverAddr='\" + serverAddr + '\\''\n\t\t\t\t+ \", username='\" + username + '\\'' + \", password='\" + password + '\\''\n\t\t\t\t+ \", endpoint='\" + endpoint + '\\'' + \", namespace='\" + namespace + '\\''\n\t\t\t\t+ \", watchDelay=\" + watchDelay + \", logName='\" + logName + '\\''\n\t\t\t\t+ \", service='\" + service + '\\'' + \", weight=\" + weight\n\t\t\t\t+ \", clusterName='\" + clusterName + '\\'' + \", group='\" + group + '\\''\n\t\t\t\t+ \", namingLoadCacheAtStart='\" + namingLoadCacheAtStart + '\\''\n\t\t\t\t+ \", metadata=\" + metadata + \", registerEnabled=\" + registerEnabled\n\t\t\t\t+ \", ip='\" + ip + '\\'' + \", networkInterface='\" + networkInterface + '\\''\n\t\t\t\t+ \", port=\" + port + \", secure=\" + secure + \", accessKey='\" + accessKey\n\t\t\t\t+ '\\'' + \", secretKey='\" + secretKey + '\\'' + \", heartBeatInterval=\"\n\t\t\t\t+ heartBeatInterval + \", heartBeatTimeout=\" + heartBeatTimeout\n\t\t\t\t+ \", ipDeleteTimeout=\" + ipDeleteTimeout + \", instanceEnabled=\"\n\t\t\t\t+ instanceEnabled + \", ephemeral=\" + ephemeral\n\t\t\t\t+ \", failureToleranceEnabled=\" + failureToleranceEnabled + '}'\n\t\t\t\t+ \", ipDeleteTimeout=\" + ipDeleteTimeout + \", failFast=\" + failFast + '}';\n\t}\n\n\tpublic void overrideFromEnv(Environment env) {\n\n\t\tif (StringUtils.isEmpty(this.getServerAddr())) {\n\t\t\tString serverAddr = env\n\t\t\t\t\t.resolvePlaceholders(\"${spring.cloud.nacos.discovery.server-addr:}\");\n\t\t\tif (StringUtils.isEmpty(serverAddr)) {\n\t\t\t\tserverAddr = env.resolvePlaceholders(\n\t\t\t\t\t\t\"${spring.cloud.nacos.server-addr:127.0.0.1:8848}\");\n\t\t\t}\n\t\t\tthis.setServerAddr(serverAddr);\n\t\t}\n\t\tif (StringUtils.isEmpty(this.getNamespace())) {\n\t\t\tthis.setNamespace(env\n\t\t\t\t\t.resolvePlaceholders(\"${spring.cloud.nacos.discovery.namespace:}\"));\n\t\t}\n\t\tif (StringUtils.isEmpty(this.getAccessKey())) {\n\t\t\tthis.setAccessKey(env\n\t\t\t\t\t.resolvePlaceholders(\"${spring.cloud.nacos.discovery.access-key:}\"));\n\t\t}\n\t\tif (StringUtils.isEmpty(this.getSecretKey())) {\n\t\t\tthis.setSecretKey(env\n\t\t\t\t\t.resolvePlaceholders(\"${spring.cloud.nacos.discovery.secret-key:}\"));\n\t\t}\n\t\tif (StringUtils.isEmpty(this.getLogName())) {\n\t\t\tthis.setLogName(\n\t\t\t\t\tenv.resolvePlaceholders(\"${spring.cloud.nacos.discovery.log-name:}\"));\n\t\t}\n\t\tif (StringUtils.isEmpty(this.getClusterName())) {\n\t\t\tthis.setClusterName(env.resolvePlaceholders(\n\t\t\t\t\t\"${spring.cloud.nacos.discovery.cluster-name:}\"));\n\t\t}\n\t\tif (StringUtils.isEmpty(this.getEndpoint())) {\n\t\t\tthis.setEndpoint(\n\t\t\t\t\tenv.resolvePlaceholders(\"${spring.cloud.nacos.discovery.endpoint:}\"));\n\t\t}\n\t\tif (StringUtils.isEmpty(this.getGroup())) {\n\t\t\tthis.setGroup(\n\t\t\t\t\tenv.resolvePlaceholders(\"${spring.cloud.nacos.discovery.group:}\"));\n\t\t}\n\t\tif (StringUtils.isEmpty(this.getUsername())) {\n\t\t\tthis.setUsername(env.resolvePlaceholders(\"${spring.cloud.nacos.username:}\"));\n\t\t}\n\t\tif (StringUtils.isEmpty(this.getPassword())) {\n\t\t\tthis.setPassword(env.resolvePlaceholders(\"${spring.cloud.nacos.password:}\"));\n\t\t}\n\t}\n\n\tpublic Properties getNacosProperties() {\n\t\tProperties properties = new Properties();\n\t\tproperties.put(SERVER_ADDR, serverAddr);\n\t\tproperties.put(USERNAME, Objects.toString(username, \"\"));\n\t\tproperties.put(PASSWORD, Objects.toString(password, \"\"));\n\t\tproperties.put(NAMESPACE, namespace);\n\t\tproperties.put(UtilAndComs.NACOS_NAMING_LOG_NAME, logName);\n\n\t\tif (endpoint.contains(\":\")) {\n\t\t\tint index = endpoint.indexOf(\":\");\n\t\t\tproperties.put(ENDPOINT, endpoint.substring(0, index));\n\t\t\tproperties.put(ENDPOINT_PORT, endpoint.substring(index + 1));\n\t\t}\n\t\telse {\n\t\t\tproperties.put(ENDPOINT, endpoint);\n\t\t}\n\n\t\tproperties.put(ACCESS_KEY, accessKey);\n\t\tproperties.put(SECRET_KEY, secretKey);\n\t\t// only used for instance.setClusterName()\n//\t\tproperties.put(CLUSTER_NAME, clusterName);\n\t\tproperties.put(NAMING_LOAD_CACHE_AT_START, namingLoadCacheAtStart);\n\n\t\tenrichNacosDiscoveryProperties(properties);\n\t\treturn properties;\n\t}\n\n\tprivate void enrichNacosDiscoveryProperties(Properties nacosDiscoveryProperties) {\n\t\tMap<String, Object> properties = PropertySourcesUtils\n\t\t\t\t.getSubProperties((ConfigurableEnvironment) environment, PREFIX);\n\t\tproperties.forEach((k, v) -> nacosDiscoveryProperties.putIfAbsent(resolveKey(k),\n\t\t\t\tString.valueOf(v)));\n\t}\n\n\tprivate String resolveKey(String key) {\n\t\tMatcher matcher = PATTERN.matcher(key);\n\t\tStringBuffer sb = new StringBuffer();\n\t\twhile (matcher.find()) {\n\t\t\tmatcher.appendReplacement(sb, matcher.group(1).toUpperCase(Locale.ROOT));\n\t\t}\n\t\tmatcher.appendTail(sb);\n\t\treturn sb.toString();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosServiceAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\nimport org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author yuhuangbin\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnDiscoveryEnabled\n@ConditionalOnNacosDiscoveryEnabled\npublic class NacosServiceAutoConfiguration {\n\n\t@Bean\n\tpublic NacosServiceManager nacosServiceManager() {\n\t\treturn new NacosServiceManager();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosServiceInstance.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\nimport java.net.URI;\nimport java.util.Map;\nimport java.util.Objects;\n\nimport org.springframework.cloud.client.ServiceInstance;\n\n/**\n * @author xiaojing\n * @author changjin wei(魏昌进)\n */\npublic class NacosServiceInstance implements ServiceInstance {\n\n\tprivate String serviceId;\n\n\tprivate String instanceId;\n\n\tprivate String host;\n\n\tprivate int port;\n\n\tprivate boolean secure;\n\n\tprivate Map<String, String> metadata;\n\n\t@Override\n\tpublic String getServiceId() {\n\t\treturn serviceId;\n\t}\n\n\t@Override\n\tpublic String getInstanceId() {\n\t\treturn instanceId;\n\t}\n\n\t@Override\n\tpublic String getHost() {\n\t\treturn host;\n\t}\n\n\t@Override\n\tpublic int getPort() {\n\t\treturn port;\n\t}\n\n\t@Override\n\tpublic boolean isSecure() {\n\t\treturn secure;\n\t}\n\n\t@Override\n\tpublic URI getUri() {\n\t\treturn ServiceInstance.createUri(this);\n\t}\n\n\t@Override\n\tpublic Map<String, String> getMetadata() {\n\t\treturn metadata;\n\t}\n\n\t@Override\n\tpublic String getScheme() {\n\t\treturn getUri().getScheme();\n\t}\n\n\tpublic void setServiceId(String serviceId) {\n\t\tthis.serviceId = serviceId;\n\t}\n\n\tpublic void setInstanceId(String instanceId) {\n\t\tthis.instanceId = instanceId;\n\t}\n\n\tpublic void setHost(String host) {\n\t\tthis.host = host;\n\t}\n\n\tpublic void setPort(int port) {\n\t\tthis.port = port;\n\t}\n\n\tpublic void setSecure(boolean secure) {\n\t\tthis.secure = secure;\n\t}\n\n\tpublic void setMetadata(Map<String, String> metadata) {\n\t\tthis.metadata = metadata;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (this == o) {\n\t\t\treturn true;\n\t\t}\n\t\tif (o == null || getClass() != o.getClass()) {\n\t\t\treturn false;\n\t\t}\n\t\tNacosServiceInstance that = (NacosServiceInstance) o;\n\n\t\treturn Objects.equals(this.serviceId, that.serviceId)\n\t\t\t\t&& Objects.equals(this.instanceId, that.instanceId)\n\t\t\t\t&& Objects.equals(this.host, that.host)\n\t\t\t\t&& this.port == that.port\n\t\t\t\t&& this.secure == that.secure\n\t\t\t\t&& Objects.equals(this.metadata, that.metadata);\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn (instanceId == null) ? 31 : (instanceId.hashCode() + 31);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosServiceManager.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\nimport java.util.Objects;\nimport java.util.Properties;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.NamingMaintainService;\nimport com.alibaba.nacos.api.naming.NamingService;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport static com.alibaba.nacos.api.NacosFactory.createMaintainService;\nimport static com.alibaba.nacos.api.NacosFactory.createNamingService;\n\n/**\n * @author yuhuangbin\n */\npublic class NacosServiceManager {\n\n\tprivate static final Logger log = LoggerFactory.getLogger(NacosServiceManager.class);\n\n\tprivate NacosDiscoveryProperties nacosDiscoveryProperties;\n\n\tprivate volatile NamingService namingService;\n\n\tprivate volatile NamingMaintainService namingMaintainService;\n\n\tpublic NamingService getNamingService() {\n\t\tif (Objects.isNull(this.namingService)) {\n\t\t\tbuildNamingService(nacosDiscoveryProperties.getNacosProperties());\n\t\t}\n\t\treturn namingService;\n\t}\n\n\t@Deprecated\n\tpublic NamingService getNamingService(Properties properties) {\n\t\tif (Objects.isNull(this.namingService)) {\n\t\t\tbuildNamingService(properties);\n\t\t}\n\t\treturn namingService;\n\t}\n\n\tpublic NamingMaintainService getNamingMaintainService(Properties properties) {\n\t\tif (Objects.isNull(namingMaintainService)) {\n\t\t\tbuildNamingMaintainService(properties);\n\t\t}\n\t\treturn namingMaintainService;\n\t}\n\n\tpublic boolean isNacosDiscoveryInfoChanged(\n\t\t\tNacosDiscoveryProperties currentNacosDiscoveryPropertiesCache) {\n\t\tif (Objects.isNull(this.nacosDiscoveryProperties)\n\t\t\t\t|| this.nacosDiscoveryProperties.equals(currentNacosDiscoveryPropertiesCache)) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\tprivate NamingMaintainService buildNamingMaintainService(Properties properties) {\n\t\tif (Objects.isNull(namingMaintainService)) {\n\t\t\tsynchronized (NacosServiceManager.class) {\n\t\t\t\tif (Objects.isNull(namingMaintainService)) {\n\t\t\t\t\tnamingMaintainService = createNamingMaintainService(properties);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn namingMaintainService;\n\t}\n\n\tprivate NamingService buildNamingService(Properties properties) {\n\t\tif (Objects.isNull(namingService)) {\n\t\t\tsynchronized (NacosServiceManager.class) {\n\t\t\t\tif (Objects.isNull(namingService)) {\n\t\t\t\t\tnamingService = createNewNamingService(properties);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn namingService;\n\t}\n\n\tprivate NamingService createNewNamingService(Properties properties) {\n\t\ttry {\n\t\t\treturn createNamingService(properties);\n\t\t}\n\t\tcatch (NacosException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\tprivate NamingMaintainService createNamingMaintainService(Properties properties) {\n\t\ttry {\n\t\t\treturn createMaintainService(properties);\n\t\t}\n\t\tcatch (NacosException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\tpublic void nacosServiceShutDown() throws NacosException {\n\t\tif (Objects.nonNull(this.namingService)) {\n\t\t\tthis.namingService.shutDown();\n\t\t\tthis.namingService = null;\n\t\t}\n\t\tif (Objects.nonNull(this.namingMaintainService)) {\n\t\t\tthis.namingMaintainService.shutDown();\n\t\t\tthis.namingMaintainService = null;\n\t\t}\n\t}\n\n\tpublic void setNacosDiscoveryProperties(NacosDiscoveryProperties nacosDiscoveryProperties) {\n\t\tthis.nacosDiscoveryProperties = nacosDiscoveryProperties;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/balancer/NacosBalancer.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.balancer;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.regex.Pattern;\nimport java.util.stream.Collectors;\n\n\nimport com.alibaba.cloud.commons.lang.StringUtils;\nimport com.alibaba.cloud.nacos.NacosServiceInstance;\nimport com.alibaba.cloud.nacos.loadbalancer.NacosLoadBalancer;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.client.naming.core.Balancer;\n\nimport org.springframework.cloud.client.ServiceInstance;\n\n/**\n * @author itmuch.com XuDaojie\n * @since 2021.1\n */\npublic class NacosBalancer extends Balancer {\n\n\tprivate static final String IPV4_REGEX = \"((2(5[0-5]|[0-4]\\\\d))|[0-1]?\\\\d{1,2})(.((2(5[0-5]|[0-4]\\\\d))|[0-1]?\\\\d{1,2})){3}\";\n\n\tprivate static final String IPV6_KEY = \"IPv6\";\n\n\t/**\n\t * Choose instance by weight.\n\t * @param instances Instance List\n\t * @return the chosen instance\n\t */\n\tpublic static Instance getHostByRandomWeight2(List<Instance> instances) {\n\t\treturn getHostByRandomWeight(instances);\n\t}\n\n\t/**\n\t * Spring Cloud LoadBalancer Choose instance by weight.\n\t * @param serviceInstances Instance List\n\t * @return the chosen instance\n\t */\n\tpublic static ServiceInstance getHostByRandomWeight3(\n\t\t\tList<ServiceInstance> serviceInstances) {\n\t\tMap<Instance, ServiceInstance> instanceMap = new HashMap<>();\n\t\tList<Instance> nacosInstance = serviceInstances.stream().map(serviceInstance -> {\n\t\t\tMap<String, String> metadata = serviceInstance.getMetadata();\n\n\t\t\t// see\n\t\t\t// com.alibaba.cloud.nacos.discovery.NacosServiceDiscovery.hostToServiceInstance()\n\t\t\tInstance instance = new Instance();\n\t\t\tinstance.setIp(serviceInstance.getHost());\n\t\t\tinstance.setPort(serviceInstance.getPort());\n\t\t\tinstance.setWeight(Double.parseDouble(metadata.get(\"nacos.weight\")));\n\t\t\tinstance.setHealthy(Boolean.parseBoolean(metadata.get(\"nacos.healthy\")));\n\t\t\tinstanceMap.put(instance, serviceInstance);\n\t\t\treturn instance;\n\t\t}).collect(Collectors.toList());\n\n\t\tInstance instance = getHostByRandomWeight2(nacosInstance);\n\t\tNacosServiceInstance nacosServiceInstance = (NacosServiceInstance) instanceMap.get(instance);\n\t\t// When local support IPv6 address stack, referred to use IPv6 address.\n\t\tif (StringUtils.isNotEmpty(NacosLoadBalancer.ipv6)) {\n\t\t\tconvertIPv4ToIPv6(nacosServiceInstance);\n\t\t}\n\t\treturn nacosServiceInstance;\n\t}\n\n\t/**\n\t * There is two type Ip,using IPv6 should use IPv6 in metadata to replace IPv4 in IP\n\t * field.\n\t */\n\tprivate static void convertIPv4ToIPv6(NacosServiceInstance instance) {\n\t\tif (Pattern.matches(IPV4_REGEX, instance.getHost())) {\n\t\t\tString ip = instance.getMetadata().get(IPV6_KEY);\n\t\t\tif (StringUtils.isNotEmpty(ip)) {\n\t\t\t\tinstance.setHost(ip);\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery;\n\nimport com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.NacosServiceManager;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author <a href=\"mailto:echooy.mxq@gmail.com\">echooymxq</a>\n **/\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnDiscoveryEnabled\n@ConditionalOnNacosDiscoveryEnabled\npublic class NacosDiscoveryAutoConfiguration {\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\tpublic NacosDiscoveryProperties nacosProperties() {\n\t\treturn new NacosDiscoveryProperties();\n\t}\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\tpublic NacosServiceDiscovery nacosServiceDiscovery(\n\t\t\tNacosDiscoveryProperties discoveryProperties,\n\t\t\tNacosServiceManager nacosServiceManager) {\n\t\treturn new NacosServiceDiscovery(discoveryProperties, nacosServiceManager);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryClient.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Optional;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.cloud.client.discovery.DiscoveryClient;\n\n/**\n * @author xiaojing\n * @author renhaojun\n * @author echooymxq\n * @author freeman\n */\npublic class NacosDiscoveryClient implements DiscoveryClient {\n\n\tprivate static final Logger log = LoggerFactory.getLogger(NacosDiscoveryClient.class);\n\n\t/**\n\t * Nacos Discovery Client Description.\n\t */\n\tpublic static final String DESCRIPTION = \"Spring Cloud Nacos Discovery Client\";\n\n\tprivate NacosServiceDiscovery serviceDiscovery;\n\n\t@Value(\"${spring.cloud.nacos.discovery.failure-tolerance-enabled:false}\")\n\tprivate boolean failureToleranceEnabled;\n\n\tpublic NacosDiscoveryClient(NacosServiceDiscovery nacosServiceDiscovery) {\n\t\tthis.serviceDiscovery = nacosServiceDiscovery;\n\t}\n\n\t@Override\n\tpublic String description() {\n\t\treturn DESCRIPTION;\n\t}\n\n\t@Override\n\tpublic List<ServiceInstance> getInstances(String serviceId) {\n\t\ttry {\n\t\t\treturn Optional.of(serviceDiscovery.getInstances(serviceId))\n\t\t\t\t\t.map(instances -> {\n\t\t\t\t\t\tServiceCache.setInstances(serviceId, instances);\n\t\t\t\t\t\treturn instances;\n\t\t\t\t\t}).get();\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tif (failureToleranceEnabled) {\n\t\t\t\treturn ServiceCache.getInstances(serviceId);\n\t\t\t}\n\t\t\tthrow new RuntimeException(\n\t\t\t\t\t\"Can not get hosts from nacos server. serviceId: \" + serviceId, e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic List<String> getServices() {\n\t\ttry {\n\t\t\treturn Optional.of(serviceDiscovery.getServices()).map(services -> {\n\t\t\t\tServiceCache.setServiceIds(services);\n\t\t\t\treturn services;\n\t\t\t}).get();\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tlog.error(\"get service name from nacos server failed.\", e);\n\t\t\treturn failureToleranceEnabled ? ServiceCache.getServiceIds()\n\t\t\t\t\t: Collections.emptyList();\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryClientConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery;\n\nimport com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.NacosServiceManager;\n\nimport org.springframework.boot.autoconfigure.AutoConfigureAfter;\nimport org.springframework.boot.autoconfigure.AutoConfigureBefore;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.cloud.client.CommonsClientAutoConfiguration;\nimport org.springframework.cloud.client.ConditionalOnBlockingDiscoveryEnabled;\nimport org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;\nimport org.springframework.cloud.client.discovery.DiscoveryClient;\nimport org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author xiaojing\n * @author echooymxq\n * @author ruansheng\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnDiscoveryEnabled\n@ConditionalOnBlockingDiscoveryEnabled\n@ConditionalOnNacosDiscoveryEnabled\n@AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class,\n\t\tCommonsClientAutoConfiguration.class })\n@AutoConfigureAfter(NacosDiscoveryAutoConfiguration.class)\npublic class NacosDiscoveryClientConfiguration {\n\n\t@Bean\n\tpublic DiscoveryClient nacosDiscoveryClient(\n\t\t\tNacosServiceDiscovery nacosServiceDiscovery) {\n\t\treturn new NacosDiscoveryClient(nacosServiceDiscovery);\n\t}\n\n\t/**\n\t * NacosWatch is no longer enabled by default .\n\t * see https://github.com/alibaba/spring-cloud-alibaba/issues/2868\n\t */\n\t@Bean\n\t@ConditionalOnMissingBean\n\t@ConditionalOnProperty(value = \"spring.cloud.nacos.discovery.watch.enabled\", matchIfMissing = false)\n\tpublic NacosWatch nacosWatch(NacosServiceManager nacosServiceManager,\n\t\t\tNacosDiscoveryProperties nacosDiscoveryProperties) {\n\t\treturn new NacosWatch(nacosServiceManager, nacosDiscoveryProperties);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryHeartBeatConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery;\n\nimport com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\n\nimport org.springframework.boot.autoconfigure.AutoConfigureAfter;\nimport org.springframework.boot.autoconfigure.condition.AnyNestedCondition;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.cloud.client.ConditionalOnBlockingDiscoveryEnabled;\nimport org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author xiaojing\n * @author echooymxq\n * @author ruansheng\n * @author zhangbin\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnDiscoveryEnabled\n@ConditionalOnBlockingDiscoveryEnabled\n@ConditionalOnNacosDiscoveryEnabled\n@AutoConfigureAfter(value = NacosDiscoveryAutoConfiguration.class,\n\t\tname = \"de.codecentric.boot.admin.server.cloud.config.AdminServerDiscoveryAutoConfiguration\")\npublic class NacosDiscoveryHeartBeatConfiguration {\n\n\t/**\n\t * Nacos HeartBeat is no longer enabled by default .\n\t * publish an event every 30 seconds\n\t * see https://github.com/alibaba/spring-cloud-alibaba/issues/2868\n\t * see https://github.com/alibaba/spring-cloud-alibaba/issues/3258\n\t */\n\t@Bean\n\t@ConditionalOnMissingBean\n\t@Conditional(NacosDiscoveryHeartBeatCondition.class)\n\tpublic NacosDiscoveryHeartBeatPublisher nacosDiscoveryHeartBeatPublisher(NacosDiscoveryProperties nacosDiscoveryProperties) {\n\t\treturn new NacosDiscoveryHeartBeatPublisher(nacosDiscoveryProperties);\n\t}\n\n\tprivate static class NacosDiscoveryHeartBeatCondition extends AnyNestedCondition {\n\n\t\tNacosDiscoveryHeartBeatCondition()  {\n\t\t\tsuper(ConfigurationPhase.REGISTER_BEAN);\n\t\t}\n\n\t\t/**\n         * Spring Cloud Gateway HeartBeat .\n\t\t */\n\t\t@ConditionalOnProperty(value = \"spring.cloud.gateway.server.webflux.discovery.locator.enabled\", matchIfMissing = false)\n\t\tstatic class GatewayLocatorHeartBeatEnabled { }\n\n\n\t\t/**\n\t\t * Spring Boot Admin HeartBeat .\n\t\t */\n\t\t@ConditionalOnBean(type = \"de.codecentric.boot.admin.server.cloud.discovery.InstanceDiscoveryListener\")\n\t\tstatic class SpringBootAdminHeartBeatEnabled { }\n\n\t\t/**\n\t\t * Nacos HeartBeat .\n\t\t */\n\t\t@ConditionalOnProperty(value = \"spring.cloud.nacos.discovery.heart-beat.enabled\", matchIfMissing = false)\n\t\tstatic class NacosDiscoveryHeartBeatEnabled { }\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryHeartBeatPublisher.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery;\n\nimport java.time.Duration;\nimport java.util.concurrent.ScheduledFuture;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.cloud.client.discovery.event.HeartbeatEvent;\nimport org.springframework.context.ApplicationEventPublisher;\nimport org.springframework.context.ApplicationEventPublisherAware;\nimport org.springframework.context.SmartLifecycle;\nimport org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;\n\n\n/**\n * @author yuhuangbin\n * @author ruansheng\n */\npublic class NacosDiscoveryHeartBeatPublisher implements ApplicationEventPublisherAware, SmartLifecycle {\n\n\tprivate static final Logger log = LoggerFactory.getLogger(NacosDiscoveryHeartBeatPublisher.class);\n\n\tprivate final NacosDiscoveryProperties nacosDiscoveryProperties;\n\n\tprivate final ThreadPoolTaskScheduler taskScheduler;\n\tprivate final AtomicLong nacosHeartBeatIndex = new AtomicLong(0);\n\tprivate final AtomicBoolean running = new AtomicBoolean(false);\n\tprivate ApplicationEventPublisher publisher;\n\tprivate ScheduledFuture<?> heartBeatFuture;\n\n\tpublic NacosDiscoveryHeartBeatPublisher(NacosDiscoveryProperties nacosDiscoveryProperties) {\n\t\tthis.nacosDiscoveryProperties = nacosDiscoveryProperties;\n\t\tthis.taskScheduler = getTaskScheduler();\n\t}\n\n\tprivate static ThreadPoolTaskScheduler getTaskScheduler() {\n\t\tThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();\n\t\ttaskScheduler.setBeanName(\"HeartBeat-Task-Scheduler\");\n\t\ttaskScheduler.initialize();\n\t\treturn taskScheduler;\n\t}\n\n\t@Override\n\tpublic void start() {\n\t\tif (this.running.compareAndSet(false, true)) {\n\t\t\tlog.info(\"Start nacos heartBeat task scheduler.\");\n\t\t\tthis.heartBeatFuture = this.taskScheduler.scheduleWithFixedDelay(\n\t\t\t\t\tthis::publishHeartBeat, Duration.ofMillis(this.nacosDiscoveryProperties.getWatchDelay()));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void stop() {\n\t\tif (this.running.compareAndSet(true, false)) {\n\t\t\tif (this.heartBeatFuture != null) {\n\t\t\t\t// shutdown current user-thread,\n\t\t\t\t// then the other daemon-threads will terminate automatic.\n\t\t\t\tthis.taskScheduler.shutdown();\n\t\t\t\tthis.heartBeatFuture.cancel(true);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isAutoStartup() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isRunning() {\n\t\treturn this.running.get();\n\t}\n\n\t@Override\n\tpublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {\n\t\tthis.publisher = applicationEventPublisher;\n\t}\n\n\t/**\n\t * nacos doesn't support watch now , publish an event every 30 seconds.\n\t */\n\tpublic void publishHeartBeat() {\n\t\tHeartbeatEvent event = new HeartbeatEvent(this, nacosHeartBeatIndex.getAndIncrement());\n\t\tthis.publisher.publishEvent(event);\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosServiceDiscovery.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.NacosServiceInstance;\nimport com.alibaba.cloud.nacos.NacosServiceManager;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.NamingService;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\n\nimport org.springframework.cloud.client.ServiceInstance;\n\n/**\n * @author <a href=\"mailto:echooy.mxq@gmail.com\">echooymxq</a>\n * @author changjin wei(魏昌进)\n **/\npublic class NacosServiceDiscovery {\n\n\tprivate NacosDiscoveryProperties discoveryProperties;\n\n\tprivate NacosServiceManager nacosServiceManager;\n\n\tpublic NacosServiceDiscovery(NacosDiscoveryProperties discoveryProperties,\n\t\t\tNacosServiceManager nacosServiceManager) {\n\t\tthis.discoveryProperties = discoveryProperties;\n\t\tthis.nacosServiceManager = nacosServiceManager;\n\t}\n\n\t/**\n\t * Return all instances for the given service.\n\t * @param serviceId id of service\n\t * @return list of instances\n\t * @throws NacosException nacosException\n\t */\n\tpublic List<ServiceInstance> getInstances(String serviceId) throws NacosException {\n\t\tString group = discoveryProperties.getGroup();\n\t\tList<Instance> instances = namingService().selectInstances(serviceId, group,\n\t\t\t\ttrue);\n\t\treturn hostToServiceInstanceList(instances, serviceId);\n\t}\n\n\t/**\n\t * Return the names of all services.\n\t * @return list of service names\n\t * @throws NacosException nacosException\n\t */\n\tpublic List<String> getServices() throws NacosException {\n\t\tString group = discoveryProperties.getGroup();\n\t\tListView<String> services = namingService().getServicesOfServer(1,\n\t\t\t\tInteger.MAX_VALUE, group);\n\t\treturn services.getData();\n\t}\n\n\tpublic static List<ServiceInstance> hostToServiceInstanceList(\n\t\t\tList<Instance> instances, String serviceId) {\n\t\tList<ServiceInstance> result = new ArrayList<>(instances.size());\n\t\tfor (Instance instance : instances) {\n\t\t\tServiceInstance serviceInstance = hostToServiceInstance(instance, serviceId);\n\t\t\tif (serviceInstance != null) {\n\t\t\t\tresult.add(serviceInstance);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic static ServiceInstance hostToServiceInstance(Instance instance,\n\t\t\tString serviceId) {\n\t\tif (instance == null || !instance.isEnabled() || !instance.isHealthy()) {\n\t\t\treturn null;\n\t\t}\n\t\tNacosServiceInstance nacosServiceInstance = new NacosServiceInstance();\n\t\tnacosServiceInstance.setHost(instance.getIp());\n\t\tnacosServiceInstance.setPort(instance.getPort());\n\t\tnacosServiceInstance.setServiceId(serviceId);\n\t\tnacosServiceInstance.setInstanceId(instance.getInstanceId());\n\n\t\tMap<String, String> metadata = new HashMap<>();\n\t\tmetadata.put(\"nacos.instanceId\", instance.getInstanceId());\n\t\tmetadata.put(\"nacos.weight\", instance.getWeight() + \"\");\n\t\tmetadata.put(\"nacos.healthy\", instance.isHealthy() + \"\");\n\t\tmetadata.put(\"nacos.cluster\", instance.getClusterName() + \"\");\n\t\tif (instance.getMetadata() != null) {\n\t\t\tmetadata.putAll(instance.getMetadata());\n\t\t}\n\t\tmetadata.put(\"nacos.ephemeral\", String.valueOf(instance.isEphemeral()));\n\t\tnacosServiceInstance.setMetadata(metadata);\n\n\t\tif (metadata.containsKey(\"secure\")) {\n\t\t\tboolean secure = Boolean.parseBoolean(metadata.get(\"secure\"));\n\t\t\tnacosServiceInstance.setSecure(secure);\n\t\t}\n\t\treturn nacosServiceInstance;\n\t}\n\n\tprivate NamingService namingService() {\n\t\treturn nacosServiceManager.getNamingService();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosWatch.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.NacosServiceManager;\nimport com.alibaba.nacos.api.naming.NamingService;\nimport com.alibaba.nacos.api.naming.listener.Event;\nimport com.alibaba.nacos.api.naming.listener.EventListener;\nimport com.alibaba.nacos.api.naming.listener.NamingEvent;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.DisposableBean;\nimport org.springframework.context.SmartLifecycle;\n\n/**\n * @author xiaojing\n * @author yuhuangbin\n * @author pengfei.lu\n * @author ruansheng\n */\npublic class NacosWatch implements SmartLifecycle, DisposableBean {\n\n\tprivate static final Logger log = LoggerFactory.getLogger(NacosWatch.class);\n\n\tprivate final Map<String, EventListener> listenerMap = new ConcurrentHashMap<>(16);\n\n\tprivate final AtomicBoolean running = new AtomicBoolean(false);\n\n\tprivate final NacosServiceManager nacosServiceManager;\n\n\tprivate final NacosDiscoveryProperties properties;\n\n\tpublic NacosWatch(NacosServiceManager nacosServiceManager,\n\t\t\tNacosDiscoveryProperties properties) {\n\t\tthis.nacosServiceManager = nacosServiceManager;\n\t\tthis.properties = properties;\n\t}\n\n\t@Override\n\tpublic boolean isAutoStartup() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void stop(Runnable callback) {\n\t\tthis.stop();\n\t\tcallback.run();\n\t}\n\n\t@Override\n\tpublic void start() {\n\t\tif (this.running.compareAndSet(false, true)) {\n\t\t\tEventListener eventListener = listenerMap.computeIfAbsent(buildKey(),\n\t\t\t\t\tevent -> new EventListener() {\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic void onEvent(Event event) {\n\t\t\t\t\t\t\tif (event instanceof NamingEvent namingEvent) {\n\t\t\t\t\t\t\t\tList<Instance> instances = namingEvent.getInstances();\n\t\t\t\t\t\t\t\tOptional<Instance> instanceOptional = selectCurrentInstance(\n\t\t\t\t\t\t\t\t\t\tinstances);\n\t\t\t\t\t\t\t\tinstanceOptional.ifPresent(currentInstance -> {\n\t\t\t\t\t\t\t\t\tresetIfNeeded(currentInstance);\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\tNamingService namingService = nacosServiceManager.getNamingService();\n\t\t\ttry {\n\t\t\t\tnamingService.subscribe(properties.getService(), properties.getGroup(),\n\t\t\t\t\t\tArrays.asList(properties.getClusterName()), eventListener);\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\t\t\t\tlog.error(\"namingService subscribe failed, properties:{}\", properties, e);\n\t\t\t}\n\n\t\t}\n\t}\n\n\tprivate String buildKey() {\n\t\treturn String.join(\":\", properties.getService(), properties.getGroup());\n\t}\n\n\tprivate void resetIfNeeded(Instance instance) {\n\t\tif (!properties.getMetadata().equals(instance.getMetadata())) {\n\t\t\tproperties.setMetadata(instance.getMetadata());\n\t\t}\n\t}\n\n\tprivate Optional<Instance> selectCurrentInstance(List<Instance> instances) {\n\t\treturn instances.stream()\n\t\t\t\t.filter(instance -> properties.getIp().equals(instance.getIp())\n\t\t\t\t\t\t&& properties.getPort() == instance.getPort())\n\t\t\t\t.findFirst();\n\t}\n\n\t@Override\n\tpublic void stop() {\n\t\tif (this.running.compareAndSet(true, false)) {\n\n\t\t\tEventListener eventListener = listenerMap.get(buildKey());\n\t\t\ttry {\n\t\t\t\tNamingService namingService = nacosServiceManager.getNamingService();\n\t\t\t\tnamingService.unsubscribe(properties.getService(), properties.getGroup(),\n\t\t\t\t\t\tArrays.asList(properties.getClusterName()), eventListener);\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\t\t\t\tlog.error(\"namingService unsubscribe failed, properties:{}\", properties,\n\t\t\t\t\t\te);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isRunning() {\n\t\treturn this.running.get();\n\t}\n\n\t@Override\n\tpublic int getPhase() {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic void destroy() {\n\t\tthis.stop();\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/ServiceCache.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClient;\n\nimport org.springframework.cloud.client.ServiceInstance;\n\n/**\n * Service cache.\n * <p>\n * Cache serviceIds and corresponding instances in Nacos.\n * <p>\n * It's very useful to query services and instances on runtime, but it's not real-time,\n * depends on {@link NacosDiscoveryClient} or {@link NacosReactiveDiscoveryClient}\n * {@code getServices(), getInstances(..)} invoke.\n *\n * @author freeman\n * @since 2021.0.1.0\n */\npublic final class ServiceCache {\n\n\tprivate ServiceCache() {\n\t}\n\n\tprivate static List<String> services = Collections.emptyList();\n\n\tprivate static Map<String, List<ServiceInstance>> instancesMap = new ConcurrentHashMap<>();\n\n\t/**\n\t * Set instances for specific service.\n\t * @param serviceId service id\n\t * @param instances service instances\n\t */\n\tpublic static void setInstances(String serviceId, List<ServiceInstance> instances) {\n\t\tinstancesMap.put(serviceId, Collections.unmodifiableList(instances));\n\t}\n\n\t/**\n\t * Get instances for specific service.\n\t * @param serviceId service id\n\t * @return service instances\n\t */\n\tpublic static List<ServiceInstance> getInstances(String serviceId) {\n\t\treturn Optional.ofNullable(instancesMap.get(serviceId))\n\t\t\t\t.orElse(Collections.emptyList());\n\t}\n\n\t/**\n\t * Set all services.\n\t * @param serviceIds all services\n\t * @deprecated since 2021.0.1.1, use {@link #setServiceIds(List)} instead.\n\t */\n\t@Deprecated\n\tpublic static void set(List<String> serviceIds) {\n\t\tservices = Collections.unmodifiableList(serviceIds);\n\t}\n\n\t/**\n\t * Set all services.\n\t * @param serviceIds all services\n\t * @since 2021.0.1.1\n\t */\n\tpublic static void setServiceIds(List<String> serviceIds) {\n\t\tservices = Collections.unmodifiableList(serviceIds);\n\t}\n\n\t/**\n\t * Get all services.\n\t * @return all services\n\t * @deprecated since 2021.0.1.1, use {@link #getServiceIds()} instead.\n\t */\n\t@Deprecated\n\tpublic static List<String> get() {\n\t\treturn services;\n\t}\n\n\t/**\n\t * Get all services.\n\t * @return all services\n\t * @since 2021.0.1.1\n\t */\n\tpublic static List<String> getServiceIds() {\n\t\treturn services;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/actuate/health/NacosDiscoveryHealthIndicator.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery.actuate.health;\n\nimport com.alibaba.cloud.nacos.NacosServiceManager;\nimport com.alibaba.nacos.api.naming.NamingService;\n\nimport org.springframework.boot.health.contributor.AbstractHealthIndicator;\nimport org.springframework.boot.health.contributor.Health;\nimport org.springframework.boot.health.contributor.HealthIndicator;\n\n/**\n * The {@link HealthIndicator} for Nacos Discovery.\n *\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n * @since 2.2.0\n * @see HealthIndicator\n */\npublic class NacosDiscoveryHealthIndicator extends AbstractHealthIndicator {\n\n\t/**\n\t * status up.\n\t */\n\tprivate static final String STATUS_UP = \"UP\";\n\n\t/**\n\t * status down.\n\t */\n\tprivate static final String STATUS_DOWN = \"DOWN\";\n\n\tprivate NacosServiceManager nacosServiceManager;\n\n\t@Deprecated\n\tprivate NamingService namingService;\n\n\tpublic NacosDiscoveryHealthIndicator(NacosServiceManager nacosServiceManager) {\n\t\tthis.nacosServiceManager = nacosServiceManager;\n\t}\n\n\t@Deprecated\n\tpublic NacosDiscoveryHealthIndicator(NamingService namingService) {\n\t\tthis.namingService = namingService;\n\t}\n\n\t@Override\n\tprotected void doHealthCheck(Health.Builder builder) throws Exception {\n\t\t// Just return \"UP\" or \"DOWN\"\n\t\tString status = nacosServiceManager.getNamingService().getServerStatus();\n\t\t// Set the status to Builder\n\t\tbuilder.status(status);\n\t\tswitch (status) {\n\t\tcase STATUS_UP -> builder.up();\n\t\tcase STATUS_DOWN -> builder.down();\n\t\tdefault -> builder.unknown();\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/configclient/NacosConfigServerAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery.configclient;\n\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport jakarta.annotation.PostConstruct;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.cloud.config.server.config.ConfigServerProperties;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.util.StringUtils;\n\n/**\n * Extra configuration for config server if it happens to be registered with Nacos.\n *\n * @author JevonYang\n */\n@Configuration(proxyBeanMethods = false)\n@EnableConfigurationProperties\n@ConditionalOnClass({NacosDiscoveryProperties.class, ConfigServerProperties.class})\npublic class NacosConfigServerAutoConfiguration {\n\n\t@Autowired(required = false)\n\tprivate NacosDiscoveryProperties properties;\n\n\t@Autowired(required = false)\n\tprivate ConfigServerProperties server;\n\n\t@PostConstruct\n\tpublic void init() {\n\t\tif (this.properties == null || this.server == null) {\n\t\t\treturn;\n\t\t}\n\t\tString prefix = this.server.getPrefix();\n\t\tif (StringUtils.hasText(prefix) && !StringUtils\n\t\t\t\t.hasText(this.properties.getMetadata().get(\"configPath\"))) {\n\t\t\tthis.properties.getMetadata().put(\"configPath\", prefix);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/configclient/NacosDiscoveryClientConfigServiceBootstrapConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery.configclient;\n\nimport com.alibaba.cloud.nacos.NacosServiceAutoConfiguration;\nimport com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration;\nimport com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration;\nimport com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration;\nimport com.alibaba.cloud.nacos.util.UtilIPv6AutoConfiguration;\n\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.cloud.config.client.ConfigServicePropertySourceLocator;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * Helper for config client that wants to lookup the config server via discovery.\n *\n * @author JevonYang\n */\n@ConditionalOnClass(ConfigServicePropertySourceLocator.class)\n@ConditionalOnProperty(value = \"spring.cloud.config.discovery.enabled\",\n\t\tmatchIfMissing = false)\n@Configuration(proxyBeanMethods = false)\n@ImportAutoConfiguration({ NacosDiscoveryAutoConfiguration.class,\n\t\tNacosServiceAutoConfiguration.class, NacosDiscoveryClientConfiguration.class,\n\t\tNacosReactiveDiscoveryClientConfiguration.class, UtilIPv6AutoConfiguration.class })\npublic class NacosDiscoveryClientConfigServiceBootstrapConfiguration {\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/reactive/NacosReactiveDiscoveryClient.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery.reactive;\n\nimport java.util.function.Function;\n\nimport com.alibaba.cloud.nacos.discovery.NacosServiceDiscovery;\nimport com.alibaba.cloud.nacos.discovery.ServiceCache;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.reactivestreams.Publisher;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport reactor.core.publisher.Flux;\nimport reactor.core.publisher.Mono;\nimport reactor.core.scheduler.Schedulers;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;\n\n/**\n * @author <a href=\"mailto:echooy.mxq@gmail.com\">echooymxq</a>\n * @author freeman\n **/\npublic class NacosReactiveDiscoveryClient implements ReactiveDiscoveryClient {\n\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(NacosReactiveDiscoveryClient.class);\n\n\tprivate NacosServiceDiscovery serviceDiscovery;\n\n\t@Value(\"${spring.cloud.nacos.discovery.failure-tolerance-enabled:false}\")\n\tprivate boolean failureToleranceEnabled;\n\n\tpublic NacosReactiveDiscoveryClient(NacosServiceDiscovery nacosServiceDiscovery) {\n\t\tthis.serviceDiscovery = nacosServiceDiscovery;\n\t}\n\n\t@Override\n\tpublic String description() {\n\t\treturn \"Spring Cloud Nacos Reactive Discovery Client\";\n\t}\n\n\t@Override\n\tpublic Flux<ServiceInstance> getInstances(String serviceId) {\n\n\t\treturn Mono.justOrEmpty(serviceId).flatMapMany(loadInstancesFromNacos())\n\t\t\t\t.subscribeOn(Schedulers.boundedElastic());\n\t}\n\n\tprivate Function<String, Publisher<ServiceInstance>> loadInstancesFromNacos() {\n\t\treturn serviceId -> {\n\t\t\ttry {\n\t\t\t\treturn Mono.justOrEmpty(serviceDiscovery.getInstances(serviceId))\n\t\t\t\t\t\t.flatMapMany(instances -> {\n\t\t\t\t\t\t\tServiceCache.setInstances(serviceId, instances);\n\t\t\t\t\t\t\treturn Flux.fromIterable(instances);\n\t\t\t\t\t\t});\n\t\t\t}\n\t\t\tcatch (NacosException e) {\n\t\t\t\tlog.error(\"get service instance[{}] from nacos error!\", serviceId, e);\n\t\t\t\treturn failureToleranceEnabled\n\t\t\t\t\t\t? Flux.fromIterable(ServiceCache.getInstances(serviceId))\n\t\t\t\t\t\t: Flux.empty();\n\t\t\t}\n\t\t};\n\t}\n\n\t@Override\n\tpublic Flux<String> getServices() {\n\t\treturn Flux.defer(() -> {\n\t\t\ttry {\n\t\t\t\treturn Mono.justOrEmpty(serviceDiscovery.getServices())\n\t\t\t\t\t\t.flatMapMany(services -> {\n\t\t\t\t\t\t\tServiceCache.setServiceIds(services);\n\t\t\t\t\t\t\treturn Flux.fromIterable(services);\n\t\t\t\t\t\t});\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\t\t\t\tlog.error(\"get services from nacos server fail,\", e);\n\t\t\t\treturn failureToleranceEnabled\n\t\t\t\t\t\t? Flux.fromIterable(ServiceCache.getServiceIds())\n\t\t\t\t\t\t: Flux.empty();\n\t\t\t}\n\t\t}).subscribeOn(Schedulers.boundedElastic());\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/reactive/NacosReactiveDiscoveryClientConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery.reactive;\n\nimport com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;\nimport com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration;\nimport com.alibaba.cloud.nacos.discovery.NacosServiceDiscovery;\n\nimport org.springframework.boot.autoconfigure.AutoConfigureAfter;\nimport org.springframework.boot.autoconfigure.AutoConfigureBefore;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;\nimport org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled;\nimport org.springframework.cloud.client.ReactiveCommonsClientAutoConfiguration;\nimport org.springframework.cloud.client.discovery.composite.reactive.ReactiveCompositeDiscoveryClientAutoConfiguration;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author <a href=\"mailto:echooy.mxq@gmail.com\">echooymxq</a>\n **/\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnDiscoveryEnabled\n@ConditionalOnReactiveDiscoveryEnabled\n@ConditionalOnNacosDiscoveryEnabled\n@AutoConfigureAfter({ NacosDiscoveryAutoConfiguration.class,\n\t\tReactiveCompositeDiscoveryClientAutoConfiguration.class })\n@AutoConfigureBefore({ ReactiveCommonsClientAutoConfiguration.class })\npublic class NacosReactiveDiscoveryClientConfiguration {\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\tpublic NacosReactiveDiscoveryClient nacosReactiveDiscoveryClient(\n\t\t\tNacosServiceDiscovery nacosServiceDiscovery) {\n\t\treturn new NacosReactiveDiscoveryClient(nacosServiceDiscovery);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosDiscoveryEndpoint.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.endpoint;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.NacosServiceManager;\nimport com.alibaba.nacos.api.naming.NamingService;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.boot.actuate.endpoint.annotation.Endpoint;\nimport org.springframework.boot.actuate.endpoint.annotation.ReadOperation;\n\n/**\n * Endpoint for nacos discovery, get nacos properties and subscribed services.\n *\n * @author xiaojing\n */\n@Endpoint(id = \"nacosdiscovery\")\npublic class NacosDiscoveryEndpoint {\n\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(NacosDiscoveryEndpoint.class);\n\n\tprivate NacosServiceManager nacosServiceManager;\n\n\tprivate NacosDiscoveryProperties nacosDiscoveryProperties;\n\n\tpublic NacosDiscoveryEndpoint(NacosServiceManager nacosServiceManager,\n\t\t\tNacosDiscoveryProperties nacosDiscoveryProperties) {\n\t\tthis.nacosServiceManager = nacosServiceManager;\n\t\tthis.nacosDiscoveryProperties = nacosDiscoveryProperties;\n\t}\n\n\t/**\n\t * @return nacos discovery endpoint\n\t */\n\t@ReadOperation\n\tpublic Map<String, Object> nacosDiscovery() {\n\t\tMap<String, Object> result = new HashMap<>();\n\t\tresult.put(\"NacosDiscoveryProperties\", nacosDiscoveryProperties);\n\n\t\tNamingService namingService = nacosServiceManager.getNamingService();\n\t\tList<ServiceInfo> subscribe = Collections.emptyList();\n\n\t\ttry {\n\t\t\tsubscribe = namingService.getSubscribeServices();\n\t\t\tfor (ServiceInfo serviceInfo : subscribe) {\n\t\t\t\tList<Instance> instances = namingService.getAllInstances(\n\t\t\t\t\t\tserviceInfo.getName(), serviceInfo.getGroupName());\n\t\t\t\tserviceInfo.setHosts(instances);\n\t\t\t}\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tlog.error(\"get subscribe services from nacos fail,\", e);\n\t\t}\n\t\tresult.put(\"subscribe\", subscribe);\n\t\treturn result;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosDiscoveryEndpointAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.endpoint;\n\nimport com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.NacosServiceManager;\nimport com.alibaba.cloud.nacos.discovery.actuate.health.NacosDiscoveryHealthIndicator;\n\nimport org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;\nimport org.springframework.boot.actuate.endpoint.annotation.Endpoint;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator;\nimport org.springframework.boot.health.contributor.HealthIndicator;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * The AutoConfiguration class for Nacos Discovery's Endpoints.\n *\n * @author xiaojing\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnClass(Endpoint.class)\n@ConditionalOnNacosDiscoveryEnabled\npublic class NacosDiscoveryEndpointAutoConfiguration {\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\t@ConditionalOnAvailableEndpoint\n\tpublic NacosDiscoveryEndpoint nacosDiscoveryEndpoint(\n\t\t\tNacosServiceManager nacosServiceManager,\n\t\t\tNacosDiscoveryProperties nacosDiscoveryProperties) {\n\t\treturn new NacosDiscoveryEndpoint(nacosServiceManager, nacosDiscoveryProperties);\n\t}\n\n\t@Bean\n\t@ConditionalOnProperty(name = \"spring.cloud.nacos.discovery.health-indicator.enabled\", havingValue = \"true\", matchIfMissing = false)\n\t@ConditionalOnEnabledHealthIndicator(\"nacos-discovery\")\n\tpublic HealthIndicator nacosDiscoveryHealthIndicator(NacosServiceManager nacosServiceManager) {\n\t\treturn new NacosDiscoveryHealthIndicator(nacosServiceManager);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/event/NacosDiscoveryInfoChangedEvent.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.event;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\n\nimport org.springframework.context.ApplicationEvent;\n\n/**\n * @author yuhuangbin\n */\npublic class NacosDiscoveryInfoChangedEvent extends ApplicationEvent {\n\n\tpublic NacosDiscoveryInfoChangedEvent(\n\t\t\tNacosDiscoveryProperties nacosDiscoveryProperties) {\n\t\tsuper(nacosDiscoveryProperties);\n\t}\n\n\t@Override\n\tpublic NacosDiscoveryProperties getSource() {\n\t\treturn (NacosDiscoveryProperties) super.getSource();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/loadbalancer/ConditionalOnLoadBalancerNacos.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.loadbalancer;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\n\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ElementType.TYPE, ElementType.METHOD})\n@ConditionalOnProperty(value = \"spring.cloud.loadbalancer.nacos.enabled\", havingValue = \"true\")\npublic @interface ConditionalOnLoadBalancerNacos {\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/loadbalancer/DefaultLoadBalancerAlgorithm.java",
    "content": "/*\n * Copyright 2023-present the original author or 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\npackage com.alibaba.cloud.nacos.loadbalancer;\n\nimport java.util.List;\n\nimport com.alibaba.cloud.nacos.balancer.NacosBalancer;\n\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.cloud.client.loadbalancer.Request;\nimport org.springframework.core.Ordered;\n\n/**\n * This is a default implementation of load balancing algorithm.\n * use {@link com.alibaba.cloud.nacos.balancer.NacosBalancer}\n *\n * @author <a href=\"mailto:zhangbin1010@qq.com\">zhangbinhub</a>\n */\npublic class DefaultLoadBalancerAlgorithm implements LoadBalancerAlgorithm {\n\t@Override\n\tpublic String getServiceId() {\n\t\treturn LoadBalancerAlgorithm.DEFAULT_SERVICE_ID;\n\t}\n\n\t@Override\n\tpublic ServiceInstance getInstance(Request<?> request, List<ServiceInstance> serviceInstances) {\n\t\treturn NacosBalancer.getHostByRandomWeight3(serviceInstances);\n\t}\n\n\t@Override\n\tpublic int getOrder() {\n\t\treturn Ordered.LOWEST_PRECEDENCE;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/loadbalancer/LoadBalancerAlgorithm.java",
    "content": "/*\n * Copyright 2023-present the original author or 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\npackage com.alibaba.cloud.nacos.loadbalancer;\n\nimport java.util.List;\n\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.cloud.client.loadbalancer.Request;\nimport org.springframework.core.Ordered;\n\n/**\n * Load Balancer algorithm interface.\n * When expanding the load balancing algorithm, implement this interface and register it as a bean.\n *\n * @author <a href=\"mailto:zhangbin1010@qq.com\">zhangbinhub</a>\n */\npublic interface LoadBalancerAlgorithm extends Ordered {\n\t/**\n\t * default service id.\n\t */\n\tString DEFAULT_SERVICE_ID = \"defaultServiceId\";\n\n\tString getServiceId();\n\n\tServiceInstance getInstance(Request<?> request, List<ServiceInstance> serviceInstances);\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/loadbalancer/LoadBalancerNacosAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.loadbalancer;\n\nimport com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;\n\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration\n * Auto-configuration} that sets up LoadBalancer for Nacos.\n */\n@Configuration(proxyBeanMethods = false)\n@EnableConfigurationProperties\n@ConditionalOnLoadBalancerNacos\n@ConditionalOnNacosDiscoveryEnabled\n@LoadBalancerClients(defaultConfiguration = NacosLoadBalancerClientConfiguration.class)\npublic class LoadBalancerNacosAutoConfiguration {\n\t@Bean\n\tpublic LoadBalancerAlgorithm defaultLoadBalancerAlgorithm() {\n\t\treturn new DefaultLoadBalancerAlgorithm();\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/loadbalancer/NacosLoadBalancer.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.loadbalancer;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.regex.Pattern;\nimport java.util.stream.Collectors;\n\nimport com.alibaba.cloud.commons.lang.StringUtils;\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.util.InetIPv6Utils;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport jakarta.annotation.PostConstruct;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport reactor.core.publisher.Mono;\n\nimport org.springframework.beans.factory.ObjectProvider;\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.cloud.client.loadbalancer.DefaultResponse;\nimport org.springframework.cloud.client.loadbalancer.EmptyResponse;\nimport org.springframework.cloud.client.loadbalancer.Request;\nimport org.springframework.cloud.client.loadbalancer.Response;\nimport org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier;\nimport org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;\nimport org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;\n\n/**\n * see original.\n * {@link org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer}\n *\n * @author XuDaojie\n * @since 2021.1\n */\npublic class NacosLoadBalancer implements ReactorServiceInstanceLoadBalancer {\n\n\tprivate static final Logger log = LoggerFactory.getLogger(NacosLoadBalancer.class);\n\n\tprivate final String serviceId;\n\n\tprivate final ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;\n\n\tprivate final NacosDiscoveryProperties nacosDiscoveryProperties;\n\n\tprivate static final String IPV4_REGEX = \"((2(5[0-5]|[0-4]\\\\d))|[0-1]?\\\\d{1,2})(.((2(5[0-5]|[0-4]\\\\d))|[0-1]?\\\\d{1,2})){3}\";\n\n\tprivate static final String IPV6_KEY = \"IPv6\";\n\t/**\n\t * Storage local valid IPv6 address, it's a flag whether local machine support IPv6 address stack.\n\t */\n\tpublic static String ipv6;\n\n\tprivate final InetIPv6Utils inetIPv6Utils;\n\n\tprivate final List<ServiceInstanceFilter> serviceInstanceFilters;\n\n\tprivate final Map<String, LoadBalancerAlgorithm> loadBalancerAlgorithmMap;\n\n\t@PostConstruct\n\tpublic void init() {\n\t\tString ip = nacosDiscoveryProperties.getIp();\n\t\tif (StringUtils.isNotEmpty(ip)) {\n\t\t\tipv6 = Pattern.matches(IPV4_REGEX, ip) ? nacosDiscoveryProperties.getMetadata().get(IPV6_KEY) : ip;\n\t\t}\n\t\telse {\n\t\t\tipv6 = inetIPv6Utils.findIPv6Address();\n\t\t}\n\t}\n\n\tprivate List<ServiceInstance> filterInstanceByIpType(List<ServiceInstance> instances) {\n\t\tif (StringUtils.isNotEmpty(ipv6)) {\n\t\t\tList<ServiceInstance> ipv6InstanceList = new ArrayList<>();\n\t\t\tfor (ServiceInstance instance : instances) {\n\t\t\t\tif (Pattern.matches(IPV4_REGEX, instance.getHost())) {\n\t\t\t\t\tif (StringUtils.isNotEmpty(instance.getMetadata().get(IPV6_KEY))) {\n\t\t\t\t\t\tipv6InstanceList.add(instance);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tipv6InstanceList.add(instance);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Provider has no IPv6, should use IPv4.\n\t\t\tif (ipv6InstanceList.isEmpty()) {\n\t\t\t\treturn instances.stream()\n\t\t\t\t\t\t.filter(instance -> Pattern.matches(IPV4_REGEX, instance.getHost()))\n\t\t\t\t\t\t.collect(Collectors.toList());\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn ipv6InstanceList;\n\t\t\t}\n\t\t}\n\t\treturn instances.stream()\n\t\t\t\t.filter(instance -> Pattern.matches(IPV4_REGEX, instance.getHost()))\n\t\t\t\t.collect(Collectors.toList());\n\t}\n\n\tpublic NacosLoadBalancer(\n\t\t\tObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider,\n\t\t\tString serviceId, NacosDiscoveryProperties nacosDiscoveryProperties, InetIPv6Utils inetIPv6Utils,\n\t\t\tList<ServiceInstanceFilter> serviceInstanceFilters,\n\t\t\tMap<String, LoadBalancerAlgorithm> loadBalancerAlgorithmMap) {\n\t\tthis.serviceId = serviceId;\n\t\tthis.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;\n\t\tthis.nacosDiscoveryProperties = nacosDiscoveryProperties;\n\t\tthis.inetIPv6Utils = inetIPv6Utils;\n\t\tthis.serviceInstanceFilters = serviceInstanceFilters;\n\t\tthis.loadBalancerAlgorithmMap = loadBalancerAlgorithmMap;\n\t}\n\n\t@Override\n\tpublic Mono<Response<ServiceInstance>> choose(Request request) {\n\t\tServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider\n\t\t\t\t.getIfAvailable(NoopServiceInstanceListSupplier::new);\n\t\treturn supplier.get(request).next().map(serviceInstances -> getInstanceResponse(request, serviceInstances));\n\t}\n\n\tprivate Response<ServiceInstance> getInstanceResponse(Request<?> request,\n\t\t\tList<ServiceInstance> serviceInstances) {\n\t\tif (serviceInstances.isEmpty()) {\n\t\t\tlog.warn(\"No servers available for service: {}\", this.serviceId);\n\t\t\treturn new EmptyResponse();\n\t\t}\n\n\t\ttry {\n\t\t\tString clusterName = this.nacosDiscoveryProperties.getClusterName();\n\n\t\t\tList<ServiceInstance> instancesToChoose = serviceInstances;\n\t\t\tif (StringUtils.isNotBlank(clusterName)) {\n\t\t\t\tList<ServiceInstance> sameClusterInstances = serviceInstances.stream()\n\t\t\t\t\t\t.filter(serviceInstance -> {\n\t\t\t\t\t\t\tString cluster = serviceInstance.getMetadata()\n\t\t\t\t\t\t\t\t\t.get(\"nacos.cluster\");\n\t\t\t\t\t\t\treturn StringUtils.equals(cluster, clusterName);\n\t\t\t\t\t\t}).collect(Collectors.toList());\n\t\t\t\tif (!CollectionUtils.isEmpty(sameClusterInstances)) {\n\t\t\t\t\tinstancesToChoose = sameClusterInstances;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlog.warn(\n\t\t\t\t\t\t\"A cross-cluster call occurs，name = {}, clusterName = {}, instance = {}\",\n\t\t\t\t\t\tserviceId, clusterName, serviceInstances);\n\t\t\t}\n\t\t\tinstancesToChoose = this.filterInstanceByIpType(instancesToChoose);\n\n\t\t\t// Filter the service list sequentially based on the order number\n\t\t\tfor (ServiceInstanceFilter filter : serviceInstanceFilters) {\n\t\t\t\tinstancesToChoose = filter.filterInstance(request, instancesToChoose);\n\t\t\t}\n\n\t\t\tServiceInstance instance;\n\t\t\t// Find the corresponding load balancing algorithm through the service ID and select the final service instance\n\t\t\tif (loadBalancerAlgorithmMap.containsKey(serviceId)) {\n\t\t\t\tinstance = loadBalancerAlgorithmMap.get(serviceId).getInstance(request, instancesToChoose);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tinstance = loadBalancerAlgorithmMap.get(LoadBalancerAlgorithm.DEFAULT_SERVICE_ID)\n\t\t\t\t\t\t.getInstance(request, instancesToChoose);\n\t\t\t}\n\n\t\t\treturn new DefaultResponse(instance);\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tlog.warn(\"NacosLoadBalancer error\", e);\n\t\t\treturn null;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/loadbalancer/NacosLoadBalancerClientConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.loadbalancer;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.util.InetIPv6Utils;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.cloud.client.ConditionalOnBlockingDiscoveryEnabled;\nimport org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;\nimport org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled;\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.cloud.client.discovery.DiscoveryClient;\nimport org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;\nimport org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;\nimport org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;\nimport org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;\nimport org.springframework.context.ConfigurableApplicationContext;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.core.env.Environment;\n\n/**\n * {@link ServiceInstanceListSupplier} don't use cache.<br>\n * <br>\n * 1. LoadBalancerCache causes information such as the weight of the service instance to\n * be changed without immediate effect.<br>\n * 2. Nacos itself supports caching.\n *\n * @author XuDaojie\n * @since 2021.1\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnLoadBalancerNacos\n@ConditionalOnDiscoveryEnabled\npublic class NacosLoadBalancerClientConfiguration {\n\n\tprivate static final int REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER = 183827465;\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\tpublic ReactorLoadBalancer<ServiceInstance> nacosLoadBalancer(Environment environment,\n\t\t\tLoadBalancerClientFactory loadBalancerClientFactory,\n\t\t\tNacosDiscoveryProperties nacosDiscoveryProperties,\n\t\t\tInetIPv6Utils inetIPv6Utils,\n\t\t\tList<ServiceInstanceFilter> serviceInstanceFilters,\n\t\t\tList<LoadBalancerAlgorithm> loadBalancerAlgorithms) {\n\t\tString name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);\n\t\tMap<String, LoadBalancerAlgorithm> loadBalancerAlgorithmMap = new HashMap<>();\n\t\tloadBalancerAlgorithms.forEach(loadBalancerAlgorithm -> {\n\t\t\tif (!loadBalancerAlgorithmMap.containsKey(loadBalancerAlgorithm.getServiceId())) {\n\t\t\t\tloadBalancerAlgorithmMap.put(loadBalancerAlgorithm.getServiceId(), loadBalancerAlgorithm);\n\t\t\t}\n\t\t});\n\t\treturn new NacosLoadBalancer(\n\t\t\t\tloadBalancerClientFactory.getLazyProvider(name,\n\t\t\t\t\t\tServiceInstanceListSupplier.class),\n\t\t\t\tname, nacosDiscoveryProperties, inetIPv6Utils,\n\t\t\t\tserviceInstanceFilters, loadBalancerAlgorithmMap);\n\t}\n\n\t@Configuration(proxyBeanMethods = false)\n\t@ConditionalOnReactiveDiscoveryEnabled\n\t@Order(REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER)\n\tpublic static class ReactiveSupportConfiguration {\n\n\t\t@Bean\n\t\t@ConditionalOnBean(ReactiveDiscoveryClient.class)\n\t\t@ConditionalOnMissingBean\n\t\t@ConditionalOnProperty(value = \"spring.cloud.loadbalancer.configurations\", havingValue = \"default\", matchIfMissing = true)\n\t\tpublic ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(\n\t\t\t\tConfigurableApplicationContext context) {\n\t\t\treturn ServiceInstanceListSupplier.builder().withDiscoveryClient()\n\t\t\t\t\t.build(context);\n\t\t}\n\n\t\t@Bean\n\t\t@ConditionalOnBean(ReactiveDiscoveryClient.class)\n\t\t@ConditionalOnMissingBean\n\t\t@ConditionalOnProperty(value = \"spring.cloud.loadbalancer.configurations\", havingValue = \"zone-preference\")\n\t\tpublic ServiceInstanceListSupplier zonePreferenceDiscoveryClientServiceInstanceListSupplier(\n\t\t\t\tConfigurableApplicationContext context) {\n\t\t\treturn ServiceInstanceListSupplier.builder().withDiscoveryClient()\n\t\t\t\t\t.withZonePreference().build(context);\n\t\t}\n\n\t}\n\n\t@Configuration(proxyBeanMethods = false)\n\t@ConditionalOnBlockingDiscoveryEnabled\n\t@Order(REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER + 1)\n\tpublic static class BlockingSupportConfiguration {\n\n\t\t@Bean\n\t\t@ConditionalOnBean(DiscoveryClient.class)\n\t\t@ConditionalOnMissingBean\n\t\t@ConditionalOnProperty(value = \"spring.cloud.loadbalancer.configurations\", havingValue = \"default\", matchIfMissing = true)\n\t\tpublic ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(\n\t\t\t\tConfigurableApplicationContext context) {\n\t\t\treturn ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient()\n\t\t\t\t\t.build(context);\n\t\t}\n\n\t\t@Bean\n\t\t@ConditionalOnBean(DiscoveryClient.class)\n\t\t@ConditionalOnMissingBean\n\t\t@ConditionalOnProperty(value = \"spring.cloud.loadbalancer.configurations\", havingValue = \"zone-preference\")\n\t\tpublic ServiceInstanceListSupplier zonePreferenceDiscoveryClientServiceInstanceListSupplier(\n\t\t\t\tConfigurableApplicationContext context) {\n\t\t\treturn ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient()\n\t\t\t\t\t.withZonePreference().build(context);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/loadbalancer/ServiceInstanceFilter.java",
    "content": "/*\n * Copyright 2023-present the original author or 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\npackage com.alibaba.cloud.nacos.loadbalancer;\n\nimport java.util.List;\n\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.cloud.client.loadbalancer.Request;\nimport org.springframework.core.Ordered;\n\n/**\n * Service Instance Filter interface.\n * When custom service instance list filter, implement this interface and register it as a bean.\n *\n * @author <a href=\"mailto:zhangbin1010@qq.com\">zhangbinhub</a>\n */\npublic interface ServiceInstanceFilter extends Ordered {\n\tList<ServiceInstance> filterInstance(Request<?> request, List<ServiceInstance> serviceInstances);\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosAutoServiceRegistration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.registry;\n\nimport com.alibaba.cloud.commons.lang.StringUtils;\nimport com.alibaba.cloud.nacos.event.NacosDiscoveryInfoChangedEvent;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration;\nimport org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;\nimport org.springframework.cloud.client.serviceregistry.Registration;\nimport org.springframework.cloud.client.serviceregistry.ServiceRegistry;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.event.EventListener;\nimport org.springframework.util.Assert;\n\n/**\n * @author xiaojing\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n */\npublic class NacosAutoServiceRegistration\n\t\textends AbstractAutoServiceRegistration<Registration> {\n\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(NacosAutoServiceRegistration.class);\n\n\tprivate NacosRegistration registration;\n\n\tpublic NacosAutoServiceRegistration(ApplicationContext context,\n\t\t\tServiceRegistry<Registration> serviceRegistry,\n\t\t\tAutoServiceRegistrationProperties autoServiceRegistrationProperties,\n\t\t\tNacosRegistration registration) {\n\t\tsuper(context, serviceRegistry, autoServiceRegistrationProperties);\n\t\tthis.registration = registration;\n\t}\n\n\t@Deprecated\n\tpublic void setPort(int port) {\n\t\tgetPort().set(port);\n\t}\n\n\t@Override\n\tprotected NacosRegistration getRegistration() {\n\t\tif (this.registration.getPort() < 0 && this.getPort().get() > 0) {\n\t\t\tthis.registration.setPort(this.getPort().get());\n\t\t}\n\t\tAssert.isTrue(this.registration.getPort() > 0, \"service.port has not been set\");\n\t\treturn this.registration;\n\t}\n\n\t@Override\n\tprotected NacosRegistration getManagementRegistration() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tprotected void register() {\n\t\tif (!this.registration.getNacosDiscoveryProperties().isRegisterEnabled()) {\n\t\t\tlog.debug(\"Registration disabled.\");\n\t\t\treturn;\n\t\t}\n\t\tif (this.registration.getPort() < 0) {\n\t\t\tthis.registration.setPort(getPort().get());\n\t\t}\n\t\tsuper.register();\n\t}\n\n\t@Override\n\tprotected void registerManagement() {\n\t\tif (!this.registration.getNacosDiscoveryProperties().isRegisterEnabled()) {\n\t\t\treturn;\n\t\t}\n\t\tsuper.registerManagement();\n\n\t}\n\n\t@Override\n\tprotected Object getConfiguration() {\n\t\treturn this.registration.getNacosDiscoveryProperties();\n\t}\n\n\t@Override\n\tprotected boolean isEnabled() {\n\t\treturn this.registration.getNacosDiscoveryProperties().isRegisterEnabled();\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"deprecation\")\n\tprotected String getAppName() {\n\t\tString appName = registration.getNacosDiscoveryProperties().getService();\n\t\treturn StringUtils.isEmpty(appName) ? super.getAppName() : appName;\n\t}\n\n\t@EventListener\n\tpublic void onNacosDiscoveryInfoChangedEvent(NacosDiscoveryInfoChangedEvent event) {\n\t\trestart();\n\t}\n\n\tprivate void restart() {\n\t\tthis.stop();\n\t\tthis.start();\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosGracefulShutdownDelegate.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.registry;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.context.event.ContextClosedEvent;\nimport org.springframework.lang.NonNull;\n\n/**\n * @author <a href=\"mailto:uuuyuqi@gmail.com\">uuuyuqi</a>\n */\npublic class NacosGracefulShutdownDelegate implements ApplicationListener<ContextClosedEvent>, ApplicationContextAware {\n\n\tprivate static final Logger log = LoggerFactory.getLogger(NacosGracefulShutdownDelegate.class);\n\n\tprivate final NacosAutoServiceRegistration autoServiceRegistration;\n\n\tprivate final NacosDiscoveryProperties nacosDiscoveryProperties;\n\n\tprivate ApplicationContext applicationContext;\n\n\tpublic NacosGracefulShutdownDelegate(NacosAutoServiceRegistration autoServiceRegistration,\n\t\tNacosDiscoveryProperties nacosDiscoveryProperties) {\n\t\tthis.autoServiceRegistration = autoServiceRegistration;\n\t\tthis.nacosDiscoveryProperties = nacosDiscoveryProperties;\n\t}\n\n\t@Override\n\tpublic void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n\t@Override\n\tpublic void onApplicationEvent(@NonNull ContextClosedEvent event) {\n\t\t// should NOT be executed if ContextClosedEvent published by sub contexts\n\t\tif (!applicationContext.equals(event.getApplicationContext())) {\n\t\t\tlog.debug(\"Nacos client graceful shutdown will NOT be executed \"\n\t\t\t\t\t+ \"for Spring context source: {}\", event.getApplicationContext());\n\t\t\treturn;\n\t\t}\n\n\t\tdoGracefulShutdown();\n\t}\n\n\tprotected void doGracefulShutdown() {\n\t\ttry {\n\t\t\tautoServiceRegistration.stop();\n\t\t\tInteger gracefulShutdownWaitTime = this.nacosDiscoveryProperties.getGracefulShutdownWaitTime();\n\t\t\tif (gracefulShutdownWaitTime != null && gracefulShutdownWaitTime > 0) {\n\t\t\t\tThreadUtils.sleep(gracefulShutdownWaitTime);\n\t\t\t}\n\n\t\t\tlog.info(\"Nacos client graceful shutdown has been executed successfully. \" +\n\t\t\t\t\t\"Graceful shutdown wait time is {}\", gracefulShutdownWaitTime);\n\t\t}\n\t\tcatch (Throwable t) {\n\t\t\tlog.error(\"Error occurred while performing Nacos client graceful shutdown\", t);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean supportsAsyncExecution() {\n\t\t// need wait for graceful shutdown\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosRegistration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.registry;\n\nimport java.net.URI;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.nacos.api.naming.PreservedMetadataKeys;\nimport jakarta.annotation.PostConstruct;\n\nimport org.springframework.beans.BeanUtils;\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.cloud.client.discovery.ManagementServerPortUtils;\nimport org.springframework.cloud.client.serviceregistry.Registration;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.core.env.Environment;\nimport org.springframework.util.StringUtils;\n\n/**\n * @author xiaojing\n * @author changjin wei(魏昌进)\n */\npublic class NacosRegistration implements Registration {\n\n\t/**\n\t * The metadata key of management port.\n\t */\n\tpublic static final String MANAGEMENT_PORT = \"management.port\";\n\n\t/**\n\t * The metadata key of management context-path.\n\t */\n\tpublic static final String MANAGEMENT_CONTEXT_PATH = \"management.context-path\";\n\n\t/**\n\t * The metadata key of management address.\n\t */\n\tpublic static final String MANAGEMENT_ADDRESS = \"management.address\";\n\n\t/**\n\t * The metadata key of management endpoints web base path.\n\t */\n\tpublic static final String MANAGEMENT_ENDPOINT_BASE_PATH = \"management.endpoints.web.base-path\";\n\n\tprivate List<NacosRegistrationCustomizer> registrationCustomizers;\n\n\tprivate NacosDiscoveryProperties nacosDiscoveryProperties;\n\n\tprivate ApplicationContext context;\n\n\tpublic NacosRegistration(List<NacosRegistrationCustomizer> registrationCustomizers,\n\t\t\tNacosDiscoveryProperties nacosDiscoveryProperties,\n\t\t\tApplicationContext context) {\n\t\tthis.registrationCustomizers = registrationCustomizers;\n\t\tthis.nacosDiscoveryProperties = nacosDiscoveryProperties;\n\t\tthis.context = context;\n\t}\n\n\t@PostConstruct\n\tpublic void init() {\n\n\t\tMap<String, String> metadata = nacosDiscoveryProperties.getMetadata();\n\t\tEnvironment env = context.getEnvironment();\n\n\t\tString endpointBasePath = env.getProperty(MANAGEMENT_ENDPOINT_BASE_PATH);\n\t\tif (StringUtils.hasLength(endpointBasePath)) {\n\t\t\tmetadata.put(MANAGEMENT_ENDPOINT_BASE_PATH, endpointBasePath);\n\t\t}\n\n\t\tInteger managementPort = ManagementServerPortUtils.getPort(context);\n\t\tif (null != managementPort) {\n\t\t\tmetadata.put(MANAGEMENT_PORT, managementPort.toString());\n\t\t\tString contextPath = env\n\t\t\t\t\t.getProperty(\"management.server.servlet.context-path\");\n\t\t\tString address = env.getProperty(\"management.server.address\");\n\t\t\tif (StringUtils.hasLength(contextPath)) {\n\t\t\t\tmetadata.put(MANAGEMENT_CONTEXT_PATH, contextPath);\n\t\t\t}\n\t\t\tif (StringUtils.hasLength(address)) {\n\t\t\t\tmetadata.put(MANAGEMENT_ADDRESS, address);\n\t\t\t}\n\t\t}\n\n\t\tif (null != nacosDiscoveryProperties.getHeartBeatInterval()) {\n\t\t\tmetadata.put(PreservedMetadataKeys.HEART_BEAT_INTERVAL,\n\t\t\t\t\tnacosDiscoveryProperties.getHeartBeatInterval().toString());\n\t\t}\n\t\tif (null != nacosDiscoveryProperties.getHeartBeatTimeout()) {\n\t\t\tmetadata.put(PreservedMetadataKeys.HEART_BEAT_TIMEOUT,\n\t\t\t\t\tnacosDiscoveryProperties.getHeartBeatTimeout().toString());\n\t\t}\n\t\tif (null != nacosDiscoveryProperties.getIpDeleteTimeout()) {\n\t\t\tmetadata.put(PreservedMetadataKeys.IP_DELETE_TIMEOUT,\n\t\t\t\t\tnacosDiscoveryProperties.getIpDeleteTimeout().toString());\n\t\t}\n\t\tcustomize(registrationCustomizers);\n\t}\n\n\tprotected void customize(\n\t\t\tList<NacosRegistrationCustomizer> registrationCustomizers) {\n\t\tif (registrationCustomizers != null) {\n\t\t\tfor (NacosRegistrationCustomizer customizer : registrationCustomizers) {\n\t\t\t\tcustomizer.customize(this);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getServiceId() {\n\t\treturn nacosDiscoveryProperties.getService();\n\t}\n\n\t@Override\n\tpublic String getHost() {\n\t\treturn nacosDiscoveryProperties.getIp();\n\t}\n\n\t@Override\n\tpublic int getPort() {\n\t\treturn nacosDiscoveryProperties.getPort();\n\t}\n\n\tpublic void setPort(int port) {\n\t\tthis.nacosDiscoveryProperties.setPort(port);\n\t}\n\n\t@Override\n\tpublic boolean isSecure() {\n\t\treturn nacosDiscoveryProperties.isSecure();\n\t}\n\n\t@Override\n\tpublic URI getUri() {\n\t\treturn ServiceInstance.createUri(this);\n\t}\n\n\t@Override\n\tpublic Map<String, String> getMetadata() {\n\t\treturn nacosDiscoveryProperties.getMetadata();\n\t}\n\n\tpublic boolean isRegisterEnabled() {\n\t\treturn nacosDiscoveryProperties.isRegisterEnabled();\n\t}\n\n\tpublic String getCluster() {\n\t\treturn nacosDiscoveryProperties.getClusterName();\n\t}\n\n\tpublic float getRegisterWeight() {\n\t\treturn nacosDiscoveryProperties.getWeight();\n\t}\n\n\tpublic NacosDiscoveryProperties getNacosDiscoveryProperties() {\n\t\treturn nacosDiscoveryProperties;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\tNacosDiscoveryProperties safeProp = new NacosDiscoveryProperties();\n\t\tBeanUtils.copyProperties(nacosDiscoveryProperties, safeProp);\n\t\tsafeProp.setUsername(\"******\");\n\t\tsafeProp.setPassword(\"******\");\n\t\treturn \"NacosRegistration{\" + \"nacosDiscoveryProperties=\"\n\t\t\t\t+ safeProp + '}';\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosRegistrationCustomizer.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.registry;\n\n/**\n * @author L.cm\n */\npublic interface NacosRegistrationCustomizer {\n\n\t/**\n\t * customize NacosRegistration.\n\t * @param registration NacosRegistration\n\t */\n\tvoid customize(NacosRegistration registration);\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.registry;\n\nimport java.util.List;\n\nimport com.alibaba.cloud.commons.lang.StringUtils;\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.NacosServiceManager;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.NamingService;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.cloud.client.serviceregistry.Registration;\nimport org.springframework.cloud.client.serviceregistry.ServiceRegistry;\n\nimport static org.springframework.util.ReflectionUtils.rethrowRuntimeException;\n\n/**\n * @author xiaojing\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n * @author <a href=\"mailto:78552423@qq.com\">eshun</a>\n * @author JAY\n */\npublic class NacosServiceRegistry implements ServiceRegistry<Registration> {\n\n\tprivate static final String STATUS_UP = \"UP\";\n\n\tprivate static final String STATUS_DOWN = \"DOWN\";\n\n\tprivate static final Logger log = LoggerFactory.getLogger(NacosServiceRegistry.class);\n\n\tprivate final NacosDiscoveryProperties nacosDiscoveryProperties;\n\n\tprivate final NacosServiceManager nacosServiceManager;\n\n\tpublic NacosServiceRegistry(NacosServiceManager nacosServiceManager,\n\t\t\tNacosDiscoveryProperties nacosDiscoveryProperties) {\n\t\tthis.nacosDiscoveryProperties = nacosDiscoveryProperties;\n\t\tthis.nacosServiceManager = nacosServiceManager;\n\t}\n\n\t@Override\n\tpublic void register(Registration registration) {\n\n\t\tif (StringUtils.isEmpty(registration.getServiceId())) {\n\t\t\tlog.warn(\"No service to register for nacos client...\");\n\t\t\treturn;\n\t\t}\n\n\t\tNamingService namingService = namingService();\n\t\tString serviceId = registration.getServiceId();\n\t\tString group = nacosDiscoveryProperties.getGroup();\n\n\t\tInstance instance = getNacosInstanceFromRegistration(registration);\n\n\t\ttry {\n\t\t\tnamingService.registerInstance(serviceId, group, instance);\n\t\t\tlog.info(\"nacos registry, {} {} {}:{} register finished\", group, serviceId,\n\t\t\t\t\tinstance.getIp(), instance.getPort());\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tif (nacosDiscoveryProperties.isFailFast()) {\n\t\t\t\tlog.error(\"nacos registry, {} register failed...{},\", serviceId,\n\t\t\t\t\t\tregistration.toString(), e);\n\t\t\t\trethrowRuntimeException(e);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlog.warn(\"Failfast is false. {} register failed...{},\", serviceId,\n\t\t\t\t\t\tregistration.toString(), e);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void deregister(Registration registration) {\n\n\t\tlog.info(\"De-registering from Nacos Server now...\");\n\n\t\tif (StringUtils.isEmpty(registration.getServiceId())) {\n\t\t\tlog.warn(\"No dom to de-register for nacos client...\");\n\t\t\treturn;\n\t\t}\n\n\t\tNamingService namingService = namingService();\n\t\tString serviceId = registration.getServiceId();\n\t\tString group = nacosDiscoveryProperties.getGroup();\n\n\t\ttry {\n\t\t\tnamingService.deregisterInstance(serviceId, group, registration.getHost(),\n\t\t\t\t\tregistration.getPort(), nacosDiscoveryProperties.getClusterName());\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tlog.error(\"ERR_NACOS_DEREGISTER, de-register failed...{},\",\n\t\t\t\t\tregistration.toString(), e);\n\t\t}\n\n\t\tlog.info(\"De-registration finished.\");\n\t}\n\n\t@Override\n\tpublic void close() {\n\t\ttry {\n\t\t\tnacosServiceManager.nacosServiceShutDown();\n\t\t}\n\t\tcatch (NacosException e) {\n\t\t\tlog.error(\"Nacos namingService shutDown failed\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setStatus(Registration registration, String status) {\n\n\t\tif (!STATUS_UP.equalsIgnoreCase(status)\n\t\t\t\t&& !STATUS_DOWN.equalsIgnoreCase(status)) {\n\t\t\tlog.warn(\"can't support status {},please choose UP or DOWN\", status);\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tif (STATUS_DOWN.equalsIgnoreCase(status)) {\n\t\t\t\tderegister(registration);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tregister(registration);\n\t\t\t}\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new RuntimeException(\"update nacos instance status fail\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Object getStatus(Registration registration) {\n\n\t\tString serviceName = registration.getServiceId();\n\t\tString group = nacosDiscoveryProperties.getGroup();\n\t\ttry {\n\t\t\tList<Instance> instances = namingService().getAllInstances(serviceName,\n\t\t\t\t\tgroup);\n\t\t\tfor (Instance instance : instances) {\n\t\t\t\tif (instance.getIp().equalsIgnoreCase(nacosDiscoveryProperties.getIp())\n\t\t\t\t\t\t&& instance.getPort() == nacosDiscoveryProperties.getPort()) {\n\t\t\t\t\treturn instance.isEnabled() ? STATUS_UP : STATUS_DOWN;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tlog.error(\"get all instance of {} error,\", serviceName, e);\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate Instance getNacosInstanceFromRegistration(Registration registration) {\n\t\tInstance instance = new Instance();\n\t\tinstance.setIp(registration.getHost());\n\t\tinstance.setPort(registration.getPort());\n\t\tinstance.setWeight(nacosDiscoveryProperties.getWeight());\n\t\tinstance.setClusterName(nacosDiscoveryProperties.getClusterName());\n\t\tinstance.setEnabled(nacosDiscoveryProperties.isInstanceEnabled());\n\t\tinstance.setMetadata(registration.getMetadata());\n\t\tinstance.setEphemeral(nacosDiscoveryProperties.isEphemeral());\n\t\treturn instance;\n\t}\n\n\tprivate NamingService namingService() {\n\t\treturn nacosServiceManager.getNamingService();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistryAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.registry;\n\nimport java.util.List;\n\nimport com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.NacosServiceManager;\nimport com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration;\n\nimport org.springframework.beans.factory.ObjectProvider;\nimport org.springframework.boot.autoconfigure.AutoConfigureAfter;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration;\nimport org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;\nimport org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author xiaojing\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n */\n@Configuration(proxyBeanMethods = false)\n@EnableConfigurationProperties\n@ConditionalOnNacosDiscoveryEnabled\n@ConditionalOnProperty(value = \"spring.cloud.service-registry.auto-registration.enabled\",\n\t\tmatchIfMissing = true)\n@AutoConfigureAfter({ AutoServiceRegistrationConfiguration.class,\n\t\tAutoServiceRegistrationAutoConfiguration.class,\n\t\tNacosDiscoveryAutoConfiguration.class })\npublic class NacosServiceRegistryAutoConfiguration {\n\n\t@Bean\n\tpublic NacosServiceRegistry nacosServiceRegistry(\n\t\t\tNacosServiceManager nacosServiceManager,\n\t\t\tNacosDiscoveryProperties nacosDiscoveryProperties) {\n\t\treturn new NacosServiceRegistry(nacosServiceManager, nacosDiscoveryProperties);\n\t}\n\n\t@Bean\n\t@ConditionalOnBean(AutoServiceRegistrationProperties.class)\n\tpublic NacosRegistration nacosRegistration(\n\t\t\tObjectProvider<List<NacosRegistrationCustomizer>> registrationCustomizers,\n\t\t\tNacosDiscoveryProperties nacosDiscoveryProperties,\n\t\t\tApplicationContext context) {\n\t\treturn new NacosRegistration(registrationCustomizers.getIfAvailable(),\n\t\t\t\tnacosDiscoveryProperties, context);\n\t}\n\n\t@Bean\n\t@ConditionalOnBean(AutoServiceRegistrationProperties.class)\n\tpublic NacosAutoServiceRegistration nacosAutoServiceRegistration(\n\t\t\tApplicationContext context,\n\t\t\tNacosServiceRegistry registry,\n\t\t\tAutoServiceRegistrationProperties autoServiceRegistrationProperties,\n\t\t\tNacosRegistration registration) {\n\t\treturn new NacosAutoServiceRegistration(context, registry,\n\t\t\t\tautoServiceRegistrationProperties, registration);\n\t}\n\n\t@Bean\n\t@ConditionalOnBean(NacosAutoServiceRegistration.class)\n\tpublic NacosGracefulShutdownDelegate nacosGracefulShutdownDelegate(\n\t\t\tNacosAutoServiceRegistration nacosAutoServiceRegistration,\n\t\t\tNacosDiscoveryProperties nacosDiscoveryProperties) {\n\t\treturn new NacosGracefulShutdownDelegate(nacosAutoServiceRegistration, nacosDiscoveryProperties);\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/util/InetIPv6Utils.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.util;\n\nimport java.io.IOException;\nimport java.net.Inet6Address;\nimport java.net.InetAddress;\nimport java.net.NetworkInterface;\nimport java.util.Enumeration;\nimport java.util.List;\n\nimport com.alibaba.cloud.commons.lang.StringUtils;\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\n\nimport org.springframework.cloud.commons.util.InetUtils;\nimport org.springframework.cloud.commons.util.InetUtilsProperties;\n\n/**\n * @author HH\n */\npublic class InetIPv6Utils {\n\n\tprivate final static Log log = LogFactory.getLog(InetIPv6Utils.class);\n\n\tprivate final InetUtilsProperties properties;\n\n\n\tpublic InetIPv6Utils(final InetUtilsProperties properties) {\n\t\tthis.properties = properties;\n\t}\n\n\tprivate InetUtils.HostInfo findFirstValidHostInfo() {\n\t\tInetAddress address = this.findFirstValidIPv6Address();\n\t\treturn address != null ? this.getHostInfo(address) : null;\n\t}\n\n\tprivate InetAddress findFirstValidIPv6Address() {\n\t\tInetAddress address = null;\n\n\t\ttry {\n\t\t\tfor (Enumeration<NetworkInterface> nics = NetworkInterface\n\t\t\t\t\t.getNetworkInterfaces(); nics.hasMoreElements(); ) {\n\t\t\t\tNetworkInterface ifc = nics.nextElement();\n\t\t\t\tif (ifc.isUp() || !ifc.isVirtual() || !ifc.isLoopback()) {\n\t\t\t\t\tif (address != null) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!ignoreInterface(ifc.getDisplayName())) {\n\t\t\t\t\t\tfor (Enumeration<InetAddress> addrs = ifc\n\t\t\t\t\t\t\t\t.getInetAddresses(); addrs.hasMoreElements(); ) {\n\t\t\t\t\t\t\tInetAddress inetAddress = addrs.nextElement();\n\t\t\t\t\t\t\tif (inetAddress instanceof Inet6Address\n\t\t\t\t\t\t\t\t\t// filter ::1\n\t\t\t\t\t\t\t\t\t&& !inetAddress.isLoopbackAddress()\n\t\t\t\t\t\t\t\t\t// filter fe80::/10\n\t\t\t\t\t\t\t\t\t&& !inetAddress.isLinkLocalAddress()\n\t\t\t\t\t\t\t\t\t// filter ::/128\n\t\t\t\t\t\t\t\t\t&& !inetAddress.isAnyLocalAddress()\n\t\t\t\t\t\t\t\t\t// filter fec0::/10,which was discarded, but some\n\t\t\t\t\t\t\t\t\t// address may be deployed.\n\t\t\t\t\t\t\t\t\t&& !inetAddress.isSiteLocalAddress()\n\t\t\t\t\t\t\t\t\t// filter fd00::/8\n\t\t\t\t\t\t\t\t\t&& !isUniqueLocalAddress(inetAddress)\n\t\t\t\t\t\t\t\t\t&& isPreferredAddress(inetAddress)) {\n\t\t\t\t\t\t\t\tlog.trace(\"Found non-loopback interface: \"\n\t\t\t\t\t\t\t\t\t\t+ ifc.getDisplayName());\n\t\t\t\t\t\t\t\taddress = inetAddress;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcatch (IOException e) {\n\t\t\tlog.error(\"Cannot get first non-loopback address\", e);\n\t\t}\n\t\treturn address;\n\t}\n\n\tpublic String findIPv6Address() {\n\t\tInetUtils.HostInfo hostInfo = findFirstValidHostInfo();\n\t\treturn hostInfo != null ? normalizeIPv6(hostInfo.getIpAddress()) : null;\n\t}\n\n\tprivate String normalizeIPv6(String ip) {\n\t\t// Remove the suffix of network card in IPv6 address, such as\n\t\t// 2408:400a:8c:5400:6578:5c42:77b1:bc5d%eth0\n\t\tint idx = ip.indexOf(\"%\");\n\t\treturn idx != -1 ? \"[\" + ip.substring(0, idx) + \"]\" : \"[\" + ip + \"]\";\n\t}\n\n\tprivate boolean isPreferredAddress(InetAddress address) {\n\t\tif (this.properties.isUseOnlySiteLocalInterfaces()) {\n\t\t\tfinal boolean siteLocalAddress = address.isSiteLocalAddress();\n\t\t\tif (!siteLocalAddress) {\n\t\t\t\tlog.trace(\"Ignoring address\" + address.getHostAddress());\n\t\t\t}\n\t\t\treturn siteLocalAddress;\n\t\t}\n\t\tfinal List<String> preferredNetworks = this.properties.getPreferredNetworks();\n\t\tif (preferredNetworks.isEmpty()) {\n\t\t\treturn true;\n\t\t}\n\t\tfor (String regex : preferredNetworks) {\n\t\t\tfinal String hostAddress = address.getHostAddress();\n\t\t\tif (hostAddress.matches(regex) || hostAddress.startsWith(regex)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tboolean ignoreInterface(String interfaceName) {\n\t\tfor (String regex : this.properties.getIgnoredInterfaces()) {\n\t\t\tif (interfaceName.matches(regex)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate InetUtils.HostInfo getHostInfo(final InetAddress address) {\n\t\tInetUtils.HostInfo hostInfo = new InetUtils.HostInfo();\n\t\tString hostName = address.getHostName();\n\t\tif (hostName == null) {\n\t\t\thostName = \"localhost\";\n\t\t}\n\t\thostInfo.setHostname(hostName);\n\t\tif (StringUtils.isNotEmpty(address.getHostAddress())) {\n\t\t\thostInfo.setIpAddress(address.getHostAddress());\n\t\t}\n\t\telse {\n\t\t\thostInfo.setIpAddress(StringUtils.EMPTY);\n\t\t}\n\t\treturn hostInfo;\n\t}\n\n\t/**\n\t * If the address is Unique Local Address.\n\t *\n\t * @param inetAddress {@link InetAddress}\n\t * @return {@code true} if the address is Unique Local Address, otherwise {@code false}\n\t */\n\tprivate boolean isUniqueLocalAddress(InetAddress inetAddress) {\n\t\tbyte[] ip = inetAddress.getAddress();\n\t\treturn (ip[0] & 0xff) == 0xfd;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/util/UtilIPv6AutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.util;\n\nimport com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;\nimport org.springframework.cloud.commons.util.InetUtilsProperties;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author HH\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnDiscoveryEnabled\n@ConditionalOnNacosDiscoveryEnabled\npublic class UtilIPv6AutoConfiguration {\n\n\tpublic UtilIPv6AutoConfiguration() {\n\t}\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\tpublic InetIPv6Utils inetIPv6Utils(InetUtilsProperties properties) {\n\t\treturn new InetIPv6Utils(properties);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json",
    "content": "{\"properties\": [\n    {\n      \"name\": \"spring.cloud.nacos.server-addr\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"127.0.0.1:8848\",\n      \"description\": \"nacos server address.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.discovery.server-addr\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"${spring.cloud.nacos.server-addr}\",\n      \"description\": \"nacos discovery server address.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.discovery.service\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"${spring.application.name}\",\n      \"description\": \"the service name to register, default value is ${spring.application.name}.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.discovery.enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": true,\n      \"description\": \"enable nacos discovery or not.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.discovery.instance-enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": true,\n      \"description\": \"If instance is enabled to accept request. The default value is true.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.discovery.ephemeral\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": true,\n      \"description\": \"If instance is ephemeral.The default value is true.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.discovery.namingLoadCacheAtStart\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": \"false\",\n      \"description\": \"naming load from local cache at application start .\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.discovery.watch.enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": \"false\",\n      \"description\": \"enable nacos discovery watch or not .\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.discovery.heart-beat.enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": \"false\",\n      \"description\": \"enable nacos discovery heart beat or not .\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.discovery.username\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"${spring.cloud.nacos.username}\",\n      \"description\": \"nacos discovery service's username to authenticate.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.discovery.password\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"${spring.cloud.nacos.password}\",\n      \"description\": \"nacos discovery service's password to authenticate.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.username\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"nacos userName to authenticate.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.password\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"nacos password to authenticate.\"\n    },\n    {\n      \"name\": \"spring.cloud.loadbalancer.nacos.enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": false,\n      \"description\": \"Integrate LoadBalancer or not.\"\n    },\n    {\n      \"name\": \"spring.cloud.nacos.discovery.health-indicator.enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": false,\n      \"description\": \"whether to enable nacos-discovery health indicator.\"\n    }\n]}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/native-image/reflect-config.json",
    "content": "[\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.api.grpc.auto.Metadata\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Metadata\",\n    \"methods\": [\n      {\n        \"name\": \"getClientIp\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getClientIpBytes\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getType\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTypeBytes\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.GeneratedMessageV3$FieldAccessorTable$MapFieldAccessor\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Metadata\",\n    \"methods\": [\n      {\n        \"name\": \"getDefaultInstance\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.GeneratedMessageV3$FieldAccessorTable$SingularMessageFieldAccessor\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Metadata\",\n    \"methods\": [\n      {\n        \"name\": \"newBuilder\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.TextFormat$Printer\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Metadata\",\n    \"methods\": [\n      {\n        \"name\": \"getClientIp\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getType\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.api.grpc.auto.Metadata\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Metadata$Builder\",\n    \"methods\": [\n      {\n        \"name\": \"clearClientIp\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"clearType\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getClientIp\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getClientIpBytes\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getType\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTypeBytes\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setClientIp\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setClientIpBytes\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.com.google.protobuf.ByteString\"\n        ]\n      },\n      {\n        \"name\": \"setType\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setTypeBytes\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.com.google.protobuf.ByteString\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.GeneratedMessageV3$FieldAccessorTable$SingularFieldAccessor$ReflectionInvoker\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Payload\",\n    \"methods\": [\n      {\n        \"name\": \"hasBody\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"hasMetadata\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.GeneratedMessageV3$FieldAccessorTable$SingularMessageFieldAccessor\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Payload\",\n    \"methods\": [\n      {\n        \"name\": \"getBody\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getMetadata\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"hasBody\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"hasMetadata\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.TextFormat$Printer\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Payload\",\n    \"methods\": [\n      {\n        \"name\": \"getBody\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getMetadata\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.GeneratedMessageV3$FieldAccessorTable$SingularMessageFieldAccessor\"\n    },\n    \"name\": \"com.alibaba.nacos.api.grpc.auto.Payload$Builder\",\n    \"methods\": [\n      {\n        \"name\": \"clearBody\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"clearMetadata\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getBody\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getBodyBuilder\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getMetadata\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getMetadataBuilder\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"hasBody\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"hasMetadata\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setBody\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.com.google.protobuf.Any\"\n        ]\n      },\n      {\n        \"name\": \"setMetadata\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.api.grpc.auto.Metadata\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.cache.ServiceInfoHolder\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.pojo.Instance\",\n    \"methods\": [\n      {\n        \"name\": \"getClusterName\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getInstanceHeartBeatInterval\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getInstanceHeartBeatTimeOut\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getInstanceId\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getInstanceIdGenerator\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getIp\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getIpDeleteTimeout\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getMetadata\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getPort\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getServiceName\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getWeight\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isEnabled\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isEphemeral\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isHealthy\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.pojo.Instance\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getClusterName\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getInstanceHeartBeatInterval\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getInstanceHeartBeatTimeOut\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getInstanceId\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getInstanceIdGenerator\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getIp\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getIpDeleteTimeout\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getMetadata\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getPort\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getServiceName\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getWeight\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isEnabled\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isEphemeral\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isHealthy\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setClusterName\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setEnabled\",\n        \"parameterTypes\": [\n          \"boolean\"\n        ]\n      },\n      {\n        \"name\": \"setEphemeral\",\n        \"parameterTypes\": [\n          \"boolean\"\n        ]\n      },\n      {\n        \"name\": \"setHealthy\",\n        \"parameterTypes\": [\n          \"boolean\"\n        ]\n      },\n      {\n        \"name\": \"setIp\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setMetadata\",\n        \"parameterTypes\": [\n          \"java.util.Map\"\n        ]\n      },\n      {\n        \"name\": \"setPort\",\n        \"parameterTypes\": [\n          \"int\"\n        ]\n      },\n      {\n        \"name\": \"setServiceName\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setWeight\",\n        \"parameterTypes\": [\n          \"double\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient$1\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.pojo.Instance\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setClusterName\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setEnabled\",\n        \"parameterTypes\": [\n          \"boolean\"\n        ]\n      },\n      {\n        \"name\": \"setEphemeral\",\n        \"parameterTypes\": [\n          \"boolean\"\n        ]\n      },\n      {\n        \"name\": \"setHealthy\",\n        \"parameterTypes\": [\n          \"boolean\"\n        ]\n      },\n      {\n        \"name\": \"setIp\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setMetadata\",\n        \"parameterTypes\": [\n          \"java.util.Map\"\n        ]\n      },\n      {\n        \"name\": \"setPort\",\n        \"parameterTypes\": [\n          \"int\"\n        ]\n      },\n      {\n        \"name\": \"setServiceName\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setWeight\",\n        \"parameterTypes\": [\n          \"double\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.cache.ServiceInfoHolder\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.pojo.ServiceInfo\",\n    \"methods\": [\n      {\n        \"name\": \"getCacheMillis\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getChecksum\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getClusters\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getGroupName\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getHosts\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getLastRefTime\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getName\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isAllIPs\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isReachProtectionThreshold\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isValid\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.remote.NamingClientProxyDelegate\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.pojo.ServiceInfo\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.pojo.ServiceInfo\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setAllIPs\",\n        \"parameterTypes\": [\n          \"boolean\"\n        ]\n      },\n      {\n        \"name\": \"setCacheMillis\",\n        \"parameterTypes\": [\n          \"long\"\n        ]\n      },\n      {\n        \"name\": \"setChecksum\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setClusters\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setGroupName\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setHosts\",\n        \"parameterTypes\": [\n          \"java.util.List\"\n        ]\n      },\n      {\n        \"name\": \"setLastRefTime\",\n        \"parameterTypes\": [\n          \"long\"\n        ]\n      },\n      {\n        \"name\": \"setName\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setReachProtectionThreshold\",\n        \"parameterTypes\": [\n          \"boolean\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient$1\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.pojo.ServiceInfo\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setAllIPs\",\n        \"parameterTypes\": [\n          \"boolean\"\n        ]\n      },\n      {\n        \"name\": \"setCacheMillis\",\n        \"parameterTypes\": [\n          \"long\"\n        ]\n      },\n      {\n        \"name\": \"setChecksum\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setClusters\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setGroupName\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setHosts\",\n        \"parameterTypes\": [\n          \"java.util.List\"\n        ]\n      },\n      {\n        \"name\": \"setLastRefTime\",\n        \"parameterTypes\": [\n          \"long\"\n        ]\n      },\n      {\n        \"name\": \"setName\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setReachProtectionThreshold\",\n        \"parameterTypes\": [\n          \"boolean\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.remote.request.AbstractNamingRequest\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.RpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.remote.request.AbstractNamingRequest\",\n    \"methods\": [\n      {\n        \"name\": \"getGroupName\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getModule\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getNamespace\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getServiceName\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.remote.request.InstanceRequest\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"getInstance\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getType\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient$1\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.remote.request.NotifySubscriberRequest\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setServiceInfo\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.api.naming.pojo.ServiceInfo\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.remote.request.ServiceListRequest\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"getPageNo\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getPageSize\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getSelector\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.remote.request.SubscribeServiceRequest\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"getClusters\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isSubscribe\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.remote.response.InstanceResponse\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setType\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcUtils\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.remote.response.NotifySubscriberResponse\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.remote.response.ServiceListResponse\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setCount\",\n        \"parameterTypes\": [\n          \"int\"\n        ]\n      },\n      {\n        \"name\": \"setServiceNames\",\n        \"parameterTypes\": [\n          \"java.util.List\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.remote.response.SubscribeServiceResponse\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setServiceInfo\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.api.naming.pojo.ServiceInfo\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.Payload\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.RpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.Payload\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.Payload\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient$1\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.Payload\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcConnection\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.Payload\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcUtils\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.Payload\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcConnection\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.ConnectionSetupRequest\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"getAbilities\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getClientVersion\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getLabels\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTenant\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.RpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.HealthCheckRequest\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.RpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.InternalRequest\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"getModule\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.InternalRequest\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"getModule\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcConnection\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.InternalRequest\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"getModule\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.Request\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.RpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.Request\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.Request\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient$1\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.Request\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"setRequestId\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcConnection\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.Request\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcUtils\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.Request\",\n    \"methods\": [\n      {\n        \"name\": \"getHeaders\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getRequestId\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.ServerCheckRequest\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient$1\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.request.ServerRequest\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.RpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.response.HealthCheckResponse\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.response.Response\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"setMessage\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.RpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.response.Response\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.response.Response\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"setErrorCode\",\n        \"parameterTypes\": [\n          \"int\"\n        ]\n      },\n      {\n        \"name\": \"setResultCode\",\n        \"parameterTypes\": [\n          \"int\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcConnection\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.response.Response\",\n    \"methods\": [\n      {\n        \"name\": \"setErrorCode\",\n        \"parameterTypes\": [\n          \"int\"\n        ]\n      },\n      {\n        \"name\": \"setResultCode\",\n        \"parameterTypes\": [\n          \"int\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcUtils\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.response.Response\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"getErrorCode\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getMessage\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getRequestId\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getResultCode\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isSuccess\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.remote.response.ServerCheckResponse\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setConnectionId\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.spi.NacosServiceLoader\"\n    },\n    \"name\": \"com.alibaba.nacos.client.logging.logback.NacosLogbackConfiguratorAdapterV1\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.api.naming.NamingFactory\"\n    },\n    \"name\": \"com.alibaba.nacos.client.naming.NacosNamingService\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": [\n          \"java.util.Properties\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.notify.NotifyCenter\"\n    },\n    \"name\": \"com.alibaba.nacos.common.notify.DefaultPublisher\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.common.remote.TlsConfig\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"getCertChainFile\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getCertPrivateKey\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getCertPrivateKeyPassword\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getCiphers\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getEnableTls\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getMutualAuthEnable\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getProtocols\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getSslProvider\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTrustAll\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTrustCollectionCertFile\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.common.remote.client.grpc.GrpcClient\"\n    },\n    \"name\": \"com.alibaba.nacos.common.remote.client.RpcClientTlsConfig\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.com.google.common.util.concurrent.AbstractFuture\",\n    \"fields\": [\n      {\n        \"name\": \"listeners\"\n      },\n      {\n        \"name\": \"value\"\n      },\n      {\n        \"name\": \"waiters\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.com.google.common.util.concurrent.AbstractFuture$Waiter\",\n    \"fields\": [\n      {\n        \"name\": \"next\"\n      },\n      {\n        \"name\": \"thread\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.Any\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.com.google.protobuf.Any\",\n    \"methods\": [\n      {\n        \"name\": \"getTypeUrl\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTypeUrlBytes\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getValue\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.GeneratedMessageV3$FieldAccessorTable$SingularMessageFieldAccessor\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.com.google.protobuf.Any\",\n    \"methods\": [\n      {\n        \"name\": \"newBuilder\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.TextFormat$Printer\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.com.google.protobuf.Any\",\n    \"methods\": [\n      {\n        \"name\": \"getTypeUrl\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getValue\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.Any\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.com.google.protobuf.Any$Builder\",\n    \"methods\": [\n      {\n        \"name\": \"clearTypeUrl\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"clearValue\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTypeUrl\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTypeUrlBytes\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getValue\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setTypeUrl\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setTypeUrlBytes\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.com.google.protobuf.ByteString\"\n        ]\n      },\n      {\n        \"name\": \"setValue\",\n        \"parameterTypes\": [\n          \"com.alibaba.nacos.shaded.com.google.protobuf.ByteString\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.protobuf.ExtensionRegistryFactory\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.com.google.protobuf.ExtensionRegistry\",\n    \"methods\": [\n      {\n        \"name\": \"getEmptyRegistry\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.internal.ManagedChannelImplBuilder\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.census.InternalCensusStatsAccessor\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.internal.ManagedChannelImplBuilder\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.census.InternalCensusTracingAccessor\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.NameResolverRegistry\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.internal.DnsNameResolverProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.internal.DnsNameResolver\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.internal.JndiResourceResolverFactory\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.LoadBalancerRegistry\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.internal.PickFirstLoadBalancerProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.ManagedChannelRegistry\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.NettyChannelProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.ManagedChannelRegistry\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.UdsNettyChannelProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.buffer.AbstractByteBufAllocator\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.buffer.AbstractByteBufAllocator\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.ReferenceCountUpdater\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.buffer.AbstractReferenceCountedByteBuf\",\n    \"fields\": [\n      {\n        \"name\": \"refCnt\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.Utils\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.epoll.Epoll\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ReflectiveChannelFactory\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.socket.nio.NioSocketChannel\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.ReferenceCountUtil\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.ReferenceCountUtil\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields\",\n    \"fields\": [\n      {\n        \"name\": \"producerLimit\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields\",\n    \"fields\": [\n      {\n        \"name\": \"consumerIndex\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields\",\n    \"fields\": [\n      {\n        \"name\": \"producerIndex\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField\",\n    \"fields\": [\n      {\n        \"name\": \"consumerIndex\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField\",\n    \"fields\": [\n      {\n        \"name\": \"producerIndex\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField\",\n    \"fields\": [\n      {\n        \"name\": \"producerLimit\"\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.ManagedChannelRegistry\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.okhttp.OkHttpChannelProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.Context$LazyStorage\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.override.ContextStorageOverride\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.LoadBalancerRegistry\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.grpc.util.SecretRoundRobinLoadBalancerProvider$Provider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.io.perfmark.PerfMark\"\n    },\n    \"name\": \"com.alibaba.nacos.shaded.io.perfmark.impl.SecretPerfMarkImpl$PerfMarkImpl\"\n  },\n  {\n    \"allDeclaredFields\": true,\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"methods\": [\n      {\n        \"name\": \"getConfigAbility\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getNamingAbility\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getRemoteAbility\",\n        \"parameterTypes\": []\n      }\n    ],\n    \"name\": \"com.alibaba.nacos.api.ability.ClientAbilities\",\n    \"queryAllDeclaredConstructors\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"allDeclaredFields\": true,\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"methods\": [\n      {\n        \"name\": \"isSupportRemoteMetrics\",\n        \"parameterTypes\": []\n      }\n    ],\n    \"name\": \"com.alibaba.nacos.api.config.ability.ClientConfigAbility\",\n    \"queryAllDeclaredConstructors\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"allDeclaredFields\": true,\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"methods\": [\n      {\n        \"name\": \"getModule\",\n        \"parameterTypes\": []\n      }\n    ],\n    \"name\": \"com.alibaba.nacos.api.config.remote.request.AbstractConfigRequest\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"allDeclaredFields\": true,\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.gson.Gson\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.request.AbstractConfigRequest\"\n  },\n  {\n    \"allDeclaredFields\": true,\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getConfigListenContexts\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isListen\",\n        \"parameterTypes\": []\n      }\n    ],\n    \"name\": \"com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest\",\n    \"queryAllDeclaredConstructors\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"allDeclaredFields\": true,\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"methods\": [\n      {\n        \"name\": \"getDataId\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getGroup\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getMd5\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTenant\",\n        \"parameterTypes\": []\n      }\n    ],\n    \"name\": \"com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest$ConfigListenContext\",\n    \"queryAllDeclaredConstructors\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"allDeclaredFields\": true,\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.shaded.com.google.gson.internal.bind.CollectionTypeAdapterFactory\"\n    },\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ],\n    \"name\": \"com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest$ConfigListenContext\"\n  },\n  {\n    \"allDeclaredFields\": true,\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getDataId\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getGroup\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTag\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getTenant\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isNotify\",\n        \"parameterTypes\": []\n      }\n    ],\n    \"name\": \"com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest\",\n    \"queryAllDeclaredConstructors\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"allDeclaredFields\": true,\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setChangedConfigs\",\n        \"parameterTypes\": [\n          \"java.util.List\"\n        ]\n      }\n    ],\n    \"name\": \"com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse\",\n    \"queryAllDeclaredConstructors\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"allDeclaredFields\": true,\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"name\": \"com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse$ConfigContext\",\n    \"queryAllDeclaredConstructors\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"allDeclaredFields\": true,\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setBeta\",\n        \"parameterTypes\": [\n          \"boolean\"\n        ]\n      },\n      {\n        \"name\": \"setContent\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setContentType\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setEncryptedDataKey\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      },\n      {\n        \"name\": \"setLastModified\",\n        \"parameterTypes\": [\n          \"long\"\n        ]\n      },\n      {\n        \"name\": \"setMd5\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      }\n    ],\n    \"name\": \"com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse\",\n    \"queryAllDeclaredConstructors\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"allDeclaredFields\": true,\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"methods\": [\n      {\n        \"name\": \"isSupportDeltaPush\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"isSupportRemoteMetric\",\n        \"parameterTypes\": []\n      }\n    ],\n    \"name\": \"com.alibaba.nacos.api.naming.ability.ClientNamingAbility\",\n    \"queryAllDeclaredConstructors\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"allDeclaredFields\": true,\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\"\n    },\n    \"methods\": [\n      {\n        \"name\": \"isSupportRemoteConnection\",\n        \"parameterTypes\": []\n      }\n    ],\n    \"name\": \"com.alibaba.nacos.api.remote.ability.ClientRemoteAbility\",\n    \"queryAllDeclaredConstructors\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.remote.NamingClientProxyDelegate\"\n    },\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ],\n    \"name\": \"com.alibaba.nacos.client.auth.impl.NacosClientAuthServiceImpl\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.remote.NamingClientProxyDelegate\"\n    },\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ],\n    \"name\": \"com.alibaba.nacos.client.auth.ram.RamClientAuthServiceImpl\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.api.config.ConfigFactory\"\n    },\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": [\n          \"java.util.Properties\"\n        ]\n      }\n    ],\n    \"name\": \"com.alibaba.nacos.client.config.NacosConfigService\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.nacos.client.naming.NacosNamingService\"\n    },\n    \"name\": \"com.alibaba.nacos.api.naming.pojo.Instance\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"setInstanceId\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      }\n    ]\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/native-image/resource-config.json",
    "content": "{\n  \"resources\": {\n    \"includes\": [\n      {\n        \"condition\": {\n          \"typeReachable\": \"com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.api.config.filter.IConfigFilter\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"com.alibaba.nacos.common.remote.PayloadRegistry\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.api.remote.Payload\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"com.alibaba.nacos.client.config.impl.ConfigTransportClient\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.plugin.auth.spi.client.AbstractClientAuthService\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.LoadBalancerRegistry\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.shaded.io.grpc.LoadBalancerProvider\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.ManagedChannelRegistry\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.shaded.io.grpc.ManagedChannelProvider\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"com.alibaba.nacos.shaded.io.grpc.NameResolverRegistry\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.shaded.io.grpc.NameResolverProvider\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"com.alibaba.nacos.common.utils.VersionUtils\"\n        },\n        \"pattern\": \"\\\\Qnacos-version.txt\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"com.alibaba.nacos.common.utils.ResourceUtils\"\n        },\n        \"pattern\": \"\\\\Qnacos_default_setting.properties\\\\E\"\n      }\n    ]\n  },\n  \"bundles\": []\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports",
    "content": "com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration\ncom.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration\ncom.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration\ncom.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration\ncom.alibaba.cloud.nacos.discovery.NacosDiscoveryHeartBeatConfiguration\ncom.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration\ncom.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration\ncom.alibaba.cloud.nacos.loadbalancer.LoadBalancerNacosAutoConfiguration\ncom.alibaba.cloud.nacos.NacosServiceAutoConfiguration\ncom.alibaba.cloud.nacos.util.UtilIPv6AutoConfiguration\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/spring.factories",
    "content": "org.springframework.cloud.bootstrap.BootstrapConfiguration=\\\n  com.alibaba.cloud.nacos.discovery.configclient.NacosDiscoveryClientConfigServiceBootstrapConfiguration\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/NacosDiscoveryClientTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport com.alibaba.cloud.nacos.discovery.NacosDiscoveryClient;\nimport com.alibaba.cloud.nacos.discovery.NacosServiceDiscovery;\nimport com.alibaba.cloud.nacos.discovery.ServiceCache;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport static java.util.Collections.emptyList;\nimport static java.util.Collections.singletonList;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\nimport static org.mockito.Mockito.when;\n\n/**\n * @author xiaojing\n * @author echooymxq\n * @author freeman\n */\n@ExtendWith(MockitoExtension.class)\npublic class NacosDiscoveryClientTests {\n\n\t@Mock\n\tprivate NacosServiceDiscovery serviceDiscovery;\n\n\t@Mock\n\tprivate NacosServiceInstance serviceInstance;\n\n\t@InjectMocks\n\tprivate NacosDiscoveryClient client;\n\n\t@Test\n\tpublic void testGetInstances() throws Exception {\n\n\t\twhen(serviceDiscovery.getInstances(\"service-1\"))\n\t\t\t\t.thenReturn(singletonList(serviceInstance));\n\n\t\tList<ServiceInstance> serviceInstances = client.getInstances(\"service-1\");\n\n\t\tassertThat(serviceInstances).isNotEmpty();\n\n\t}\n\n\t@Test\n\tpublic void testGetServices() throws Exception {\n\n\t\twhen(serviceDiscovery.getServices()).thenReturn(singletonList(\"service-1\"));\n\n\t\tList<String> services = client.getServices();\n\n\t\tassertThat(services).contains(\"service-1\").size().isEqualTo(1);\n\n\t}\n\n\t@Test\n\tpublic void testGetInstancesFailureToleranceEnabled() throws NacosException {\n\t\tServiceCache.setInstances(\"a\", singletonList(serviceInstance));\n\n\t\twhen(serviceDiscovery.getInstances(\"a\")).thenThrow(new NacosException());\n\t\tReflectionTestUtils.setField(client, \"failureToleranceEnabled\", true);\n\n\t\tList<ServiceInstance> instances = this.client.getInstances(\"a\");\n\n\t\tassertThat(instances).isEqualTo(singletonList(serviceInstance));\n\t}\n\n\t@Test\n\tpublic void testGetInstancesFailureToleranceDisabled() throws NacosException {\n\t\tServiceCache.setInstances(\"a\", singletonList(serviceInstance));\n\n\t\twhen(serviceDiscovery.getInstances(\"a\")).thenThrow(new NacosException());\n\t\tReflectionTestUtils.setField(client, \"failureToleranceEnabled\", false);\n\n\t\tassertThatThrownBy(() -> this.client.getInstances(\"a\"));\n\t}\n\n\t@Test\n\tpublic void testFailureToleranceEnabled() throws NacosException {\n\t\tServiceCache.setServiceIds(Arrays.asList(\"a\", \"b\"));\n\n\t\twhen(serviceDiscovery.getServices()).thenThrow(new NacosException());\n\t\tReflectionTestUtils.setField(client, \"failureToleranceEnabled\", true);\n\n\t\tList<String> services = this.client.getServices();\n\n\t\tassertThat(services).isEqualTo(Arrays.asList(\"a\", \"b\"));\n\t}\n\n\t@Test\n\tpublic void testFailureToleranceDisabled() throws NacosException {\n\t\tServiceCache.setServiceIds(Arrays.asList(\"a\", \"b\"));\n\n\t\twhen(serviceDiscovery.getServices()).thenThrow(new NacosException());\n\t\tReflectionTestUtils.setField(client, \"failureToleranceEnabled\", false);\n\n\t\tList<String> services = this.client.getServices();\n\n\t\tassertThat(services).isEqualTo(emptyList());\n\t}\n\n\t@Test\n\tpublic void testCacheIsOK() throws NacosException {\n\t\twhen(serviceDiscovery.getInstances(\"a\"))\n\t\t\t\t.thenReturn(singletonList(serviceInstance));\n\t\tthis.client.getInstances(\"a\");\n\t\tassertThat(ServiceCache.getInstances(\"a\")).isEqualTo(singletonList(serviceInstance));\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/NacosDiscoveryPropertiesServerAddressBothLevelTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\nimport com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration;\nimport com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;\nimport org.springframework.context.annotation.Configuration;\n\nimport static com.alibaba.cloud.nacos.NacosDiscoveryPropertiesServerAddressBothLevelTests.TestConfig;\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author <a href=\"mailto:lyuzb@lyuzb.com\">lyuzb</a>\n */\n@SpringBootTest(classes = TestConfig.class, properties = {\n\t\t\"spring.application.name=app\",\n\t\t\"spring.cloud.nacos.discovery.server-addr=321.321.321.321:8848\",\n\t\t\"spring.cloud.nacos.server-addr=123.123.123.123:8848\" })\npublic class NacosDiscoveryPropertiesServerAddressBothLevelTests {\n\n\t@Autowired\n\tprivate NacosDiscoveryProperties properties;\n\n\t@Test\n\tpublic void testGetServerAddr() {\n\t\tassertThat(properties.getServerAddr()).isEqualTo(\"321.321.321.321:8848\");\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@ImportAutoConfiguration({ AutoServiceRegistrationConfiguration.class,\n\t\t\tNacosDiscoveryClientConfiguration.class,\n\t\t\tNacosServiceRegistryAutoConfiguration.class })\n\tpublic static class TestConfig {\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/NacosDiscoveryPropertiesServerAddressTopLevelTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos;\n\nimport com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration;\nimport com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;\nimport org.springframework.context.annotation.Configuration;\n\nimport static com.alibaba.cloud.nacos.NacosDiscoveryPropertiesServerAddressTopLevelTests.TestConfig;\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author <a href=\"mailto:lyuzb@lyuzb.com\">lyuzb</a>\n *\n */\n@SpringBootTest(classes = TestConfig.class, properties = {\n\t\t\"spring.application.name=app\",\n\t\t\"spring.cloud.nacos.server-addr=123.123.123.123:8848\" })\npublic class NacosDiscoveryPropertiesServerAddressTopLevelTests {\n\n\t@Autowired\n\tprivate NacosDiscoveryProperties properties;\n\n\t@Test\n\tpublic void testGetServerAddr() {\n\t\tassertThat(properties.getServerAddr()).isEqualTo(\"123.123.123.123:8848\");\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@ImportAutoConfiguration({ AutoServiceRegistrationConfiguration.class,\n\t\t\tNacosDiscoveryClientConfiguration.class,\n\t\t\tNacosServiceRegistryAutoConfiguration.class })\n\tpublic static class TestConfig {\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryAutoConfigurationTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.NacosServiceAutoConfiguration;\nimport com.alibaba.cloud.nacos.util.UtilIPv6AutoConfiguration;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.boot.autoconfigure.AutoConfigurations;\nimport org.springframework.boot.test.context.runner.ApplicationContextRunner;\nimport org.springframework.cloud.commons.util.UtilAutoConfiguration;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author <a href=\"mailto:echooy.mxq@gmail.com\">echooymxq</a>\n **/\npublic class NacosDiscoveryAutoConfigurationTests {\n\n\tprivate ApplicationContextRunner contextRunner = new ApplicationContextRunner()\n\t\t\t.withConfiguration(AutoConfigurations.of(UtilAutoConfiguration.class,\n\t\t\t\t\tUtilIPv6AutoConfiguration.class,\n\t\t\t\t\tNacosServiceAutoConfiguration.class,\n\t\t\t\t\tNacosDiscoveryAutoConfiguration.class));\n\n\t@Test\n\tpublic void testDefaultInitialization() {\n\t\tcontextRunner.run(context -> {\n\t\t\tassertThat(context).hasSingleBean(NacosDiscoveryProperties.class);\n\t\t\tassertThat(context).hasSingleBean(NacosServiceDiscovery.class);\n\t\t});\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryClientConfigurationTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery;\n\nimport com.alibaba.cloud.nacos.NacosServiceAutoConfiguration;\nimport com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration;\nimport com.alibaba.cloud.nacos.util.UtilIPv6AutoConfiguration;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.boot.autoconfigure.AutoConfigurations;\nimport org.springframework.boot.test.context.runner.ApplicationContextRunner;\nimport org.springframework.cloud.client.discovery.DiscoveryClient;\nimport org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;\nimport org.springframework.cloud.commons.util.UtilAutoConfiguration;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.scheduling.TaskScheduler;\nimport org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author <a href=\"mailto:echooy.mxq@gmail.com\">echooymxq</a>\n **/\npublic class NacosDiscoveryClientConfigurationTest {\n\n\tprivate ApplicationContextRunner contextRunner = new ApplicationContextRunner()\n\t\t\t.withConfiguration(AutoConfigurations.of(\n\t\t\t\t\tAutoServiceRegistrationConfiguration.class,\n\t\t\t\t\tNacosServiceRegistryAutoConfiguration.class,\n\t\t\t\t\tUtilAutoConfiguration.class,\n\t\t\t\t\tUtilIPv6AutoConfiguration.class,\n\t\t\t\t\tNacosServiceAutoConfiguration.class,\n\t\t\t\t\tNacosDiscoveryAutoConfiguration.class,\n\t\t\t\t\tNacosDiscoveryClientConfiguration.class, this.getClass()));\n\n\t@Bean\n\tpublic TaskScheduler taskScheduler() {\n\t\treturn new ThreadPoolTaskScheduler();\n\t}\n\n\t@Test\n\tpublic void testDefaultInitialization() {\n\t\tcontextRunner.run(context -> {\n\t\t\tassertThat(context).hasSingleBean(DiscoveryClient.class);\n\t\t\t// NacosWatch is no longer enabled by default\n\t\t\tassertThat(context).doesNotHaveBean(NacosWatch.class);\n\t\t});\n\t}\n\n\t@Test\n\tpublic void testDiscoveryBlockingDisabled() {\n\t\tcontextRunner.withPropertyValues(\"spring.cloud.discovery.blocking.enabled=false\")\n\t\t\t\t.run(context -> {\n\t\t\t\t\tassertThat(context).doesNotHaveBean(DiscoveryClient.class);\n\t\t\t\t\tassertThat(context).doesNotHaveBean(NacosWatch.class);\n\t\t\t\t});\n\t}\n\n\t@Test\n\tpublic void testNacosWatchEnabled() {\n\t\tcontextRunner.withPropertyValues(\"spring.cloud.nacos.discovery.watch.enabled=true\")\n\t\t\t\t.run(context -> assertThat(context).hasSingleBean(NacosWatch.class));\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryHeartBeatConfigurationTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery;\n\nimport com.alibaba.cloud.nacos.NacosServiceAutoConfiguration;\nimport com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration;\nimport com.alibaba.cloud.nacos.util.UtilIPv6AutoConfiguration;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.boot.autoconfigure.AutoConfigurations;\nimport org.springframework.boot.test.context.runner.ApplicationContextRunner;\nimport org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;\nimport org.springframework.cloud.commons.util.UtilAutoConfiguration;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author <a href=\"mailto:zhangbin1010@qq.com\">zhangbin</a>\n **/\npublic class NacosDiscoveryHeartBeatConfigurationTest {\n\n\tprivate ApplicationContextRunner contextRunner = new ApplicationContextRunner()\n\t\t\t.withConfiguration(AutoConfigurations.of(\n\t\t\t\t\tAutoServiceRegistrationConfiguration.class,\n\t\t\t\t\tNacosServiceRegistryAutoConfiguration.class,\n\t\t\t\t\tUtilAutoConfiguration.class,\n\t\t\t\t\tUtilIPv6AutoConfiguration.class,\n\t\t\t\t\tNacosServiceAutoConfiguration.class,\n\t\t\t\t\tNacosDiscoveryAutoConfiguration.class,\n\t\t\t\t\tNacosDiscoveryClientConfiguration.class,\n\t\t\t\t\tNacosDiscoveryHeartBeatConfiguration.class, this.getClass()));\n\n\t@Test\n\tpublic void testDefaultNacosDiscoveryHeartBeatPublisher() {\n\t\tcontextRunner.run(context ->\n\t\t\t\tassertThat(context).doesNotHaveBean(NacosDiscoveryHeartBeatPublisher.class)\n\t\t);\n\t}\n\n\t@Test\n\tpublic void testNacosDiscoveryHeartBeatPublisherEnabledForGateway() {\n\t\tcontextRunner\n\t\t\t\t.withPropertyValues(\"spring.cloud.gateway.server.webflux.discovery.locator.enabled=true\")\n\t\t\t\t.run(context ->\n\t\t\t\t\t\tassertThat(context).hasSingleBean(NacosDiscoveryHeartBeatPublisher.class)\n\t\t\t\t);\n\t}\n\n\t@Test\n\tpublic void testNacosDiscoveryHeartBeatPublisherEnabledForProperties() {\n\t\tcontextRunner\n\t\t\t\t.withPropertyValues(\"spring.cloud.nacos.discovery.heart-beat.enabled=true\")\n\t\t\t\t.run(context ->\n\t\t\t\t\t\tassertThat(context).hasSingleBean(NacosDiscoveryHeartBeatPublisher.class)\n\t\t\t\t);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryLoadBalancerConfigurationTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery;\n\nimport com.alibaba.cloud.nacos.NacosServiceAutoConfiguration;\nimport com.alibaba.cloud.nacos.loadbalancer.LoadBalancerAlgorithm;\nimport com.alibaba.cloud.nacos.loadbalancer.LoadBalancerNacosAutoConfiguration;\nimport com.alibaba.cloud.nacos.loadbalancer.NacosLoadBalancerClientConfiguration;\nimport com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration;\nimport com.alibaba.cloud.nacos.util.UtilIPv6AutoConfiguration;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.boot.autoconfigure.AutoConfigurations;\nimport org.springframework.boot.test.context.runner.ApplicationContextRunner;\nimport org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;\nimport org.springframework.cloud.commons.util.UtilAutoConfiguration;\nimport org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author <a href=\"mailto:zhangbin1010@qq.com\">zhangbinhub</a>\n **/\npublic class NacosDiscoveryLoadBalancerConfigurationTest {\n\n\tprivate final ApplicationContextRunner contextRunner = new ApplicationContextRunner()\n\t\t\t.withConfiguration(AutoConfigurations.of(\n\t\t\t\t\tAutoServiceRegistrationConfiguration.class,\n\t\t\t\t\tNacosServiceRegistryAutoConfiguration.class,\n\t\t\t\t\tUtilAutoConfiguration.class,\n\t\t\t\t\tUtilIPv6AutoConfiguration.class,\n\t\t\t\t\tNacosServiceAutoConfiguration.class,\n\t\t\t\t\tNacosDiscoveryAutoConfiguration.class,\n\t\t\t\t\tNacosDiscoveryClientConfiguration.class,\n\t\t\t\t\tLoadBalancerAutoConfiguration.class, this.getClass()));\n\n\t@Test\n\tpublic void testNacosLoadBalancerEnabled() {\n\t\tcontextRunner.withPropertyValues(\n\t\t\t\t\"spring.cloud.loadbalancer.nacos.enabled=true\",\n\t\t\t\t\"spring.cloud.loadbalancer.client.name=testService\",\n\t\t\t\t\"spring.cloud.loadbalancer.configurations=none\")\n\t\t\t\t.withConfiguration(AutoConfigurations.of(\n\t\t\t\t\t\tLoadBalancerNacosAutoConfiguration.class,\n\t\t\t\t\t\tNacosLoadBalancerClientConfiguration.class))\n\t\t\t\t.run(context -> {\n\t\t\t\t\tassertThat(context).hasSingleBean(LoadBalancerAlgorithm.class);\n\t\t\t\t\tassertThat(context).hasBean(\"nacosLoadBalancer\");\n\t\t\t\t});\n\t}\n\n\t@Test\n\tpublic void testNacosLoadBalancerDisabled() {\n\t\tcontextRunner.withPropertyValues(\n\t\t\t\t\"spring.cloud.loadbalancer.nacos.enabled=false\",\n\t\t\t\t\"spring.cloud.loadbalancer.client.name=testService\",\n\t\t\t\t\"spring.cloud.loadbalancer.configurations=none\")\n\t\t\t\t.withConfiguration(AutoConfigurations.of(\n\t\t\t\t\t\tLoadBalancerNacosAutoConfiguration.class,\n\t\t\t\t\t\tNacosLoadBalancerClientConfiguration.class))\n\t\t\t\t.run(context -> {\n\t\t\t\t\tassertThat(context).doesNotHaveBean(LoadBalancerAlgorithm.class);\n\t\t\t\t\tassertThat(context).doesNotHaveBean(\"nacosLoadBalancer\");\n\t\t\t\t});\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/discovery/NacosServiceDiscoveryTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.NacosServiceManager;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.NamingService;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.cloud.client.ServiceInstance;\n\nimport static com.alibaba.cloud.nacos.test.NacosMockTest.serviceInstance;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\n/**\n * @author xiaojing\n * @author echooymxq\n **/\npublic class NacosServiceDiscoveryTest {\n\n\tprivate String host = \"123.123.123.123\";\n\n\tprivate int port = 8888;\n\n\tprivate String serviceName = \"test-service\";\n\n\t@Test\n\tpublic void testGetInstances() throws NacosException {\n\t\tArrayList<Instance> instances = new ArrayList<>();\n\n\t\tHashMap<String, String> map = new HashMap<>();\n\t\tmap.put(\"test-key\", \"test-value\");\n\t\tmap.put(\"secure\", \"true\");\n\n\t\tinstances.add(serviceInstance(serviceName, true, host, port, map));\n\n\t\tNacosDiscoveryProperties nacosDiscoveryProperties = mock(\n\t\t\t\tNacosDiscoveryProperties.class);\n\t\tNacosServiceManager nacosServiceManager = mock(NacosServiceManager.class);\n\n\t\tNamingService namingService = mock(NamingService.class);\n\n\t\twhen(nacosServiceManager.getNamingService())\n\t\t\t\t\t\t.thenReturn(namingService);\n\t\twhen(nacosDiscoveryProperties.getGroup()).thenReturn(\"DEFAULT\");\n\t\twhen(namingService.selectInstances(eq(serviceName), eq(\"DEFAULT\"), eq(true)))\n\t\t\t\t.thenReturn(instances);\n\n\t\tNacosServiceDiscovery serviceDiscovery = new NacosServiceDiscovery(\n\t\t\t\tnacosDiscoveryProperties, nacosServiceManager);\n\n\t\tList<ServiceInstance> serviceInstances = serviceDiscovery\n\t\t\t\t.getInstances(serviceName);\n\n\t\tassertThat(serviceInstances.size()).isEqualTo(1);\n\n\t\tServiceInstance serviceInstance = serviceInstances.get(0);\n\n\t\tassertThat(serviceInstance.getServiceId()).isEqualTo(serviceName);\n\t\tassertThat(serviceInstance.getHost()).isEqualTo(host);\n\t\tassertThat(serviceInstance.getPort()).isEqualTo(port);\n\t\tassertThat(serviceInstance.isSecure()).isEqualTo(true);\n\t\tassertThat(serviceInstance.getUri().toString())\n\t\t\t\t.isEqualTo(getUri(serviceInstance));\n\t\tassertThat(serviceInstance.getMetadata().get(\"test-key\")).isEqualTo(\"test-value\");\n\t}\n\n\t@Test\n\tpublic void testGetServices() throws NacosException {\n\t\tListView<String> nacosServices = new ListView<>();\n\n\t\tnacosServices.setData(new LinkedList<>());\n\n\t\tnacosServices.getData().add(serviceName + \"1\");\n\t\tnacosServices.getData().add(serviceName + \"2\");\n\t\tnacosServices.getData().add(serviceName + \"3\");\n\n\t\tNacosDiscoveryProperties nacosDiscoveryProperties = mock(\n\t\t\t\tNacosDiscoveryProperties.class);\n\t\tNacosServiceManager nacosServiceManager = mock(NacosServiceManager.class);\n\n\t\tNamingService namingService = mock(NamingService.class);\n\n\t\twhen(nacosServiceManager\n\t\t\t\t.getNamingService())\n\t\t\t\t\t\t.thenReturn(namingService);\n\t\twhen(nacosDiscoveryProperties.getGroup()).thenReturn(\"DEFAULT\");\n\t\twhen(namingService.getServicesOfServer(eq(1), eq(Integer.MAX_VALUE),\n\t\t\t\teq(\"DEFAULT\"))).thenReturn(nacosServices);\n\n\t\tNacosServiceDiscovery serviceDiscovery = new NacosServiceDiscovery(\n\t\t\t\tnacosDiscoveryProperties, nacosServiceManager);\n\n\t\tList<String> services = serviceDiscovery.getServices();\n\n\t\tassertThat(services.size()).isEqualTo(3);\n\t\tassertThat(services.contains(serviceName + \"1\"));\n\t\tassertThat(services.contains(serviceName + \"2\"));\n\t\tassertThat(services.contains(serviceName + \"3\"));\n\t}\n\n\tprivate String getUri(ServiceInstance instance) {\n\n\t\tif (instance.isSecure()) {\n\t\t\treturn \"https://\" + host + \":\" + port;\n\t\t}\n\n\t\treturn \"http://\" + host + \":\" + port;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/discovery/reactive/NacosReactiveDiscoveryClientConfigurationTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery.reactive;\n\nimport com.alibaba.cloud.nacos.NacosServiceAutoConfiguration;\nimport com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration;\nimport com.alibaba.cloud.nacos.util.UtilIPv6AutoConfiguration;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.boot.autoconfigure.AutoConfigurations;\nimport org.springframework.boot.test.context.runner.ApplicationContextRunner;\nimport org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;\nimport org.springframework.cloud.commons.util.UtilAutoConfiguration;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author <a href=\"mailto:echooy.mxq@gmail.com\">echooymxq</a>\n **/\npublic class NacosReactiveDiscoveryClientConfigurationTests {\n\n\tprivate ApplicationContextRunner contextRunner = new ApplicationContextRunner()\n\t\t\t.withConfiguration(AutoConfigurations.of(UtilAutoConfiguration.class,\n\t\t\t\t\tUtilIPv6AutoConfiguration.class,\n\t\t\t\t\tNacosDiscoveryAutoConfiguration.class,\n\t\t\t\t\tNacosServiceAutoConfiguration.class,\n\t\t\t\t\tNacosReactiveDiscoveryClientConfiguration.class));\n\n\t@Test\n\tpublic void testDefaultInitialization() {\n\t\tcontextRunner.run(context -> assertThat(context)\n\t\t\t\t.hasSingleBean(ReactiveDiscoveryClient.class));\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/discovery/reactive/NacosReactiveDiscoveryClientTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.discovery.reactive;\n\nimport java.util.Arrays;\n\nimport com.alibaba.cloud.nacos.discovery.NacosServiceDiscovery;\nimport com.alibaba.cloud.nacos.discovery.ServiceCache;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport reactor.core.publisher.Flux;\nimport reactor.test.StepVerifier;\n\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport static java.util.Collections.singletonList;\nimport static org.mockito.Mockito.when;\n\n/**\n * @author <a href=\"mailto:echooy.mxq@gmail.com\">echooymxq</a>\n * @author freeman\n **/\n@ExtendWith(MockitoExtension.class)\nclass NacosReactiveDiscoveryClientTests {\n\n\t@Mock\n\tprivate NacosServiceDiscovery serviceDiscovery;\n\n\t@Mock\n\tprivate ServiceInstance serviceInstance;\n\n\t@InjectMocks\n\tprivate NacosReactiveDiscoveryClient client;\n\n\t@Test\n\tvoid testGetInstances() throws NacosException {\n\n\t\twhen(serviceDiscovery.getInstances(\"reactive-service\"))\n\t\t\t\t.thenReturn(singletonList(serviceInstance));\n\n\t\tFlux<ServiceInstance> instances = this.client.getInstances(\"reactive-service\");\n\n\t\tStepVerifier.create(instances).expectNextCount(1).expectComplete().verify();\n\t}\n\n\t@Test\n\tvoid testGetServices() throws NacosException {\n\n\t\twhen(serviceDiscovery.getServices())\n\t\t\t\t.thenReturn(Arrays.asList(\"reactive-service1\", \"reactive-service2\"));\n\n\t\tFlux<String> services = this.client.getServices();\n\n\t\tStepVerifier.create(services).expectNext(\"reactive-service1\", \"reactive-service2\")\n\t\t\t\t.expectComplete().verify();\n\t}\n\n\t@Test\n\tpublic void testGetInstancesFailureToleranceEnabled() throws NacosException {\n\t\tServiceCache.setInstances(\"a\", singletonList(serviceInstance));\n\n\t\twhen(serviceDiscovery.getInstances(\"a\")).thenThrow(new NacosException());\n\t\tReflectionTestUtils.setField(client, \"failureToleranceEnabled\", true);\n\n\t\tFlux<ServiceInstance> instances = this.client.getInstances(\"a\");\n\n\t\tStepVerifier.create(instances).expectNext(serviceInstance)\n\t\t\t\t.expectComplete().verify();\n\t}\n\n\t@Test\n\tpublic void testGetInstancesFailureToleranceDisabled() throws NacosException {\n\t\tServiceCache.setInstances(\"a\", singletonList(serviceInstance));\n\n\t\twhen(serviceDiscovery.getInstances(\"a\")).thenThrow(new NacosException());\n\t\tReflectionTestUtils.setField(client, \"failureToleranceEnabled\", false);\n\n\t\tFlux<ServiceInstance> instances = this.client.getInstances(\"a\");\n\n\t\tStepVerifier.create(instances).expectComplete().verify();\n\t}\n\n\t@Test\n\tpublic void testFailureToleranceEnabled() throws NacosException {\n\t\tServiceCache.setServiceIds(Arrays.asList(\"a\", \"b\"));\n\n\t\twhen(serviceDiscovery.getServices()).thenThrow(new NacosException());\n\t\tReflectionTestUtils.setField(client, \"failureToleranceEnabled\", true);\n\n\n\t\tFlux<String> services = this.client.getServices();\n\n\t\tStepVerifier.create(services).expectNext(\"a\", \"b\")\n\t\t\t\t.expectComplete().verify();\n\t}\n\n\t@Test\n\tpublic void testFailureToleranceDisabled() throws NacosException {\n\t\tServiceCache.setServiceIds(Arrays.asList(\"a\", \"b\"));\n\n\t\twhen(serviceDiscovery.getServices()).thenThrow(new NacosException());\n\t\tReflectionTestUtils.setField(client, \"failureToleranceEnabled\", false);\n\n\t\tFlux<String> services = this.client.getServices();\n\n\t\tStepVerifier.create(services).expectComplete().verify();\n\t}\n\n\t@Test\n\tpublic void testCacheIsOK() throws NacosException, InterruptedException {\n\t\twhen(serviceDiscovery.getInstances(\"a\"))\n\t\t\t\t.thenReturn(singletonList(serviceInstance));\n\t\tFlux<ServiceInstance> instances = this.client.getInstances(\"a\");\n\n\t\tinstances = instances.doOnComplete(() -> {\n\t\t\tif (!ServiceCache.getInstances(\"a\").equals(singletonList(serviceInstance))) {\n\t\t\t\tthrow new RuntimeException();\n\t\t\t}\n\t\t});\n\n\t\tStepVerifier.create(instances)\n\t\t\t\t\t\t.expectNext(serviceInstance)\n\t\t\t\t\t\t.expectComplete().verify();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/registry/MockNamingService.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.registry;\n\nimport java.util.Collections;\nimport java.util.List;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.NamingService;\nimport com.alibaba.nacos.api.naming.listener.EventListener;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.naming.selector.NamingSelector;\nimport com.alibaba.nacos.api.selector.AbstractSelector;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic abstract class MockNamingService implements NamingService {\n\n\t@Override\n\tpublic void registerInstance(String serviceName, String ip, int port)\n\t\t\tthrows NacosException {\n\n\t}\n\n\t@Override\n\tpublic void registerInstance(String serviceName, String groupName, String ip,\n\t\t\tint port) throws NacosException {\n\n\t}\n\n\t@Override\n\tpublic void registerInstance(String serviceName, String ip, int port,\n\t\t\tString clusterName) throws NacosException {\n\n\t}\n\n\t@Override\n\tpublic void registerInstance(String serviceName, String groupName, String ip,\n\t\t\tint port, String clusterName) throws NacosException {\n\n\t}\n\n\t@Override\n\tpublic void registerInstance(String serviceName, Instance instance)\n\t\t\tthrows NacosException {\n\n\t}\n\n\t@Override\n\tpublic void registerInstance(String serviceName, String groupName, Instance instance)\n\t\t\tthrows NacosException {\n\n\t}\n\n\t@Override\n\tpublic void batchRegisterInstance(String serviceName, String groupName, List<Instance> instances) throws NacosException {\n\n\t}\n\n\t@Override\n\tpublic void batchDeregisterInstance(String serviceName, String groupName, List<Instance> instances) throws NacosException {\n\n\t}\n\n\t@Override\n\tpublic void deregisterInstance(String serviceName, String ip, int port)\n\t\t\tthrows NacosException {\n\n\t}\n\n\t@Override\n\tpublic void deregisterInstance(String serviceName, String groupName, String ip,\n\t\t\tint port) throws NacosException {\n\n\t}\n\n\t@Override\n\tpublic void deregisterInstance(String serviceName, String ip, int port,\n\t\t\tString clusterName) throws NacosException {\n\n\t}\n\n\t@Override\n\tpublic void deregisterInstance(String serviceName, String groupName, String ip,\n\t\t\tint port, String clusterName) throws NacosException {\n\n\t}\n\n\t@Override\n\tpublic void deregisterInstance(String serviceName, Instance instance)\n\t\t\tthrows NacosException {\n\n\t}\n\n\t@Override\n\tpublic void deregisterInstance(String serviceName, String groupName,\n\t\t\tInstance instance) throws NacosException {\n\n\t}\n\n\t@Override\n\tpublic List<Instance> getAllInstances(String serviceName) throws NacosException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic List<Instance> getAllInstances(String serviceName, String groupName)\n\t\t\tthrows NacosException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic List<Instance> getAllInstances(String serviceName, boolean subscribe)\n\t\t\tthrows NacosException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic List<Instance> getAllInstances(String serviceName, String groupName,\n\t\t\tboolean subscribe) throws NacosException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic List<Instance> getAllInstances(String serviceName, List<String> clusters)\n\t\t\tthrows NacosException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic List<Instance> getAllInstances(String serviceName, String groupName,\n\t\t\tList<String> clusters) throws NacosException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic List<Instance> getAllInstances(String serviceName, List<String> clusters,\n\t\t\tboolean subscribe) throws NacosException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic List<Instance> getAllInstances(String serviceName, String groupName,\n\t\t\tList<String> clusters, boolean subscribe) throws NacosException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic List<Instance> selectInstances(String serviceName, boolean healthy)\n\t\t\tthrows NacosException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic List<Instance> selectInstances(String serviceName, String groupName,\n\t\t\tboolean healthy) throws NacosException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic List<Instance> selectInstances(String serviceName, boolean healthy,\n\t\t\tboolean subscribe) throws NacosException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic List<Instance> selectInstances(String serviceName, String groupName,\n\t\t\tboolean healthy, boolean subscribe) throws NacosException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic List<Instance> selectInstances(String serviceName, List<String> clusters,\n\t\t\tboolean healthy) throws NacosException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic List<Instance> selectInstances(String serviceName, String groupName,\n\t\t\tList<String> clusters, boolean healthy) throws NacosException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic List<Instance> selectInstances(String serviceName, List<String> clusters,\n\t\t\tboolean healthy, boolean subscribe) throws NacosException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic List<Instance> selectInstances(String serviceName, String groupName,\n\t\t\tList<String> clusters, boolean healthy, boolean subscribe)\n\t\t\tthrows NacosException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic Instance selectOneHealthyInstance(String serviceName) throws NacosException {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Instance selectOneHealthyInstance(String serviceName, String groupName)\n\t\t\tthrows NacosException {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Instance selectOneHealthyInstance(String serviceName, boolean subscribe)\n\t\t\tthrows NacosException {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Instance selectOneHealthyInstance(String serviceName, String groupName,\n\t\t\tboolean subscribe) throws NacosException {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Instance selectOneHealthyInstance(String serviceName, List<String> clusters)\n\t\t\tthrows NacosException {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Instance selectOneHealthyInstance(String serviceName, String groupName,\n\t\t\tList<String> clusters) throws NacosException {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Instance selectOneHealthyInstance(String serviceName, List<String> clusters,\n\t\t\tboolean subscribe) throws NacosException {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Instance selectOneHealthyInstance(String serviceName, String groupName,\n\t\t\tList<String> clusters, boolean subscribe) throws NacosException {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void subscribe(String serviceName, EventListener listener)\n\t\t\tthrows NacosException {\n\n\t}\n\n\t@Override\n\tpublic void subscribe(String serviceName, String groupName, EventListener listener)\n\t\t\tthrows NacosException {\n\n\t}\n\n\t@Override\n\tpublic void subscribe(String serviceName, List<String> clusters,\n\t\t\tEventListener listener) throws NacosException {\n\n\t}\n\n\t@Override\n\tpublic void subscribe(String serviceName, String groupName, List<String> clusters,\n\t\t\tEventListener listener) throws NacosException {\n\n\t}\n\n\t@Override\n\tpublic void unsubscribe(String serviceName, EventListener listener)\n\t\t\tthrows NacosException {\n\n\t}\n\n\t@Override\n\tpublic void unsubscribe(String serviceName, String groupName, EventListener listener)\n\t\t\tthrows NacosException {\n\n\t}\n\n\t@Override\n\tpublic void unsubscribe(String serviceName, List<String> clusters,\n\t\t\tEventListener listener) throws NacosException {\n\n\t}\n\n\t@Override\n\tpublic void unsubscribe(String serviceName, String groupName, List<String> clusters,\n\t\t\tEventListener listener) throws NacosException {\n\n\t}\n\n\t@Override\n\tpublic ListView<String> getServicesOfServer(int pageNo, int pageSize)\n\t\t\tthrows NacosException {\n\t\treturn this.emptyListView();\n\t}\n\n\t@Override\n\tpublic ListView<String> getServicesOfServer(int pageNo, int pageSize,\n\t\t\tString groupName) throws NacosException {\n\t\treturn this.emptyListView();\n\t}\n\n\t@Override\n\tpublic ListView<String> getServicesOfServer(int pageNo, int pageSize,\n\t\t\tAbstractSelector selector) throws NacosException {\n\t\treturn this.emptyListView();\n\t}\n\n\t@Override\n\tpublic ListView<String> getServicesOfServer(int pageNo, int pageSize,\n\t\t\tString groupName, AbstractSelector selector) throws NacosException {\n\t\treturn this.emptyListView();\n\t}\n\n\t@Override\n\tpublic List<ServiceInfo> getSubscribeServices() throws NacosException {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic String getServerStatus() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void shutDown() throws NacosException {\n\n\t}\n\tprivate ListView<String> emptyListView() {\n\t\tListView<String> emptyListView = new ListView<>();\n\t\temptyListView.setCount(0);\n\t\temptyListView.setData(Collections.emptyList());\n\t\treturn emptyListView;\n\t}\n\n\t@Override\n\tpublic void subscribe(String s, NamingSelector namingSelector, EventListener eventListener) throws NacosException {\n\n\t}\n\n\t@Override\n\tpublic void subscribe(String s, String s1, NamingSelector namingSelector, EventListener eventListener) throws NacosException {\n\n\t}\n\n\t@Override\n\tpublic void unsubscribe(String s, NamingSelector namingSelector, EventListener eventListener) throws NacosException {\n\n\t}\n\n\t@Override\n\tpublic void unsubscribe(String s, String s1, NamingSelector namingSelector, EventListener eventListener) throws NacosException {\n\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/registry/NacosAutoServiceRegistrationIpNetworkInterfaceTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.registry;\n\nimport java.net.Inet4Address;\nimport java.net.Inet6Address;\nimport java.net.InetAddress;\nimport java.net.NetworkInterface;\nimport java.util.Enumeration;\nimport java.util.Properties;\nimport java.util.concurrent.Future;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration;\nimport com.alibaba.nacos.api.NacosFactory;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.listener.FuzzyWatchEventWatcher;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;\nimport org.springframework.cloud.commons.util.InetUtils;\nimport org.springframework.context.annotation.Configuration;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;\n\n/**\n * @author xiaojing\n */\n\n@SpringBootTest(\n\t\tclasses = NacosAutoServiceRegistrationIpNetworkInterfaceTests.TestConfig.class,\n\t\tproperties = { \"spring.application.name=myTestService1\",\n\t\t\t\t\"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\" },\n\t\twebEnvironment = RANDOM_PORT)\npublic class NacosAutoServiceRegistrationIpNetworkInterfaceTests {\n\n\t@Autowired\n\tprivate NacosRegistration registration;\n\n\t@Autowired\n\tprivate NacosAutoServiceRegistration nacosAutoServiceRegistration;\n\n\t@Autowired\n\tprivate NacosDiscoveryProperties properties;\n\n\t@Autowired\n\tprivate InetUtils inetUtils;\n\tprivate static MockedStatic<NacosFactory> nacosFactoryMockedStatic;\n\tstatic {\n\t\tnacosFactoryMockedStatic = Mockito.mockStatic(NacosFactory.class);\n\t\tnacosFactoryMockedStatic.when(() -> NacosFactory.createNamingService((Properties) any()))\n\t\t\t\t.thenReturn(new MockNamingService() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void fuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void fuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic Future<ListView<String>> fuzzyWatchWithServiceKeys(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic Future<ListView<String>> fuzzyWatchWithServiceKeys(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void cancelFuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void cancelFuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\t\t\t\t});\n\t}\n\t@AfterAll\n\tpublic static void finished() {\n\t\tif (nacosFactoryMockedStatic != null) {\n\t\t\tnacosFactoryMockedStatic.close();\n\t\t}\n\t}\n\t@Test\n\tpublic void contextLoads() throws Exception {\n\t\tassertThat(registration).isNotNull();\n\t\tassertThat(properties).isNotNull();\n\t\tassertThat(nacosAutoServiceRegistration).isNotNull();\n\n\t\tcheckoutNacosDiscoveryServiceIP();\n\t}\n\n\tprivate void checkoutNacosDiscoveryServiceIP() {\n\t\tassertThat(registration.getHost())\n\t\t\t\t.isEqualTo(getIPFromNetworkInterface(TestConfig.netWorkInterfaceName));\n\t}\n\n\tprivate String getIPFromNetworkInterface(String networkInterface) {\n\n\t\tif (!TestConfig.hasValidNetworkInterface) {\n\t\t\treturn inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();\n\t\t}\n\n\t\ttry {\n\t\t\tNetworkInterface netInterface = NetworkInterface.getByName(networkInterface);\n\n\t\t\tEnumeration<InetAddress> inetAddress = netInterface.getInetAddresses();\n\t\t\twhile (inetAddress.hasMoreElements()) {\n\t\t\t\tInetAddress currentAddress = inetAddress.nextElement();\n\t\t\t\tif (currentAddress instanceof Inet4Address || currentAddress instanceof Inet6Address\n\t\t\t\t\t\t&& !currentAddress.isLoopbackAddress()) {\n\t\t\t\t\treturn currentAddress.getHostAddress();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn networkInterface;\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\treturn networkInterface;\n\t\t}\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@ImportAutoConfiguration({ AutoServiceRegistrationConfiguration.class,\n\t\t\tNacosDiscoveryClientConfiguration.class,\n\t\t\tNacosServiceRegistryAutoConfiguration.class })\n\tpublic static class TestConfig {\n\n\t\tstatic boolean hasValidNetworkInterface = false;\n\t\tstatic String netWorkInterfaceName;\n\n\t\tstatic {\n\n\t\t\ttry {\n\t\t\t\tEnumeration<NetworkInterface> enumeration = NetworkInterface\n\t\t\t\t\t\t.getNetworkInterfaces();\n\t\t\t\twhile (enumeration.hasMoreElements() && !hasValidNetworkInterface) {\n\t\t\t\t\tNetworkInterface networkInterface = enumeration.nextElement();\n\t\t\t\t\tEnumeration<InetAddress> inetAddress = networkInterface\n\t\t\t\t\t\t\t.getInetAddresses();\n\t\t\t\t\twhile (inetAddress.hasMoreElements()) {\n\t\t\t\t\t\tInetAddress currentAddress = inetAddress.nextElement();\n\t\t\t\t\t\tif (currentAddress instanceof Inet4Address || currentAddress instanceof Inet6Address\n\t\t\t\t\t\t\t\t&& !currentAddress.isLoopbackAddress()) {\n\t\t\t\t\t\t\thasValidNetworkInterface = true;\n\t\t\t\t\t\t\tnetWorkInterfaceName = networkInterface.getName();\n\t\t\t\t\t\t\tSystem.setProperty(\n\t\t\t\t\t\t\t\t\t\"spring.cloud.nacos.discovery.network-interface\",\n\t\t\t\t\t\t\t\t\tnetworkInterface.getName());\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\n\t\t\t}\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/registry/NacosAutoServiceRegistrationIpTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.registry;\n\nimport java.util.Properties;\nimport java.util.concurrent.Future;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration;\nimport com.alibaba.nacos.api.NacosFactory;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.listener.FuzzyWatchEventWatcher;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;\nimport org.springframework.context.annotation.Configuration;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;\n\n/**\n * @author xiaojing\n */\n\n@SpringBootTest(classes = NacosAutoServiceRegistrationIpTests.TestConfig.class,\n\t\tproperties = { \"spring.application.name=myTestService1\",\n\t\t\t\t\"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\",\n\t\t\t\t\"spring.cloud.nacos.discovery.ip=123.123.123.123\" },\n\t\twebEnvironment = RANDOM_PORT)\npublic class NacosAutoServiceRegistrationIpTests {\n\n\t@Autowired\n\tprivate NacosRegistration registration;\n\n\t@Autowired\n\tprivate NacosAutoServiceRegistration nacosAutoServiceRegistration;\n\n\t@Autowired\n\tprivate NacosDiscoveryProperties properties;\n\n\tprivate static MockedStatic<NacosFactory> nacosFactoryMockedStatic;\n\tstatic {\n\t\tnacosFactoryMockedStatic = Mockito.mockStatic(NacosFactory.class);\n\t\tnacosFactoryMockedStatic.when(() -> NacosFactory.createNamingService((Properties) any()))\n\t\t\t\t.thenReturn(new MockNamingService() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void fuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void fuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic Future<ListView<String>> fuzzyWatchWithServiceKeys(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic Future<ListView<String>> fuzzyWatchWithServiceKeys(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void cancelFuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void cancelFuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\t\t\t\t});\n\t}\n\t@AfterAll\n\tpublic static void finished() {\n\t\tif (nacosFactoryMockedStatic != null) {\n\t\t\tnacosFactoryMockedStatic.close();\n\t\t}\n\t}\n\n\t@Test\n\tpublic void contextLoads() throws Exception {\n\t\tassertThat(registration).isNotNull();\n\t\tassertThat(properties).isNotNull();\n\t\tassertThat(nacosAutoServiceRegistration).isNotNull();\n\n\t\tcheckoutNacosDiscoveryServiceIP();\n\t}\n\n\tprivate void checkoutNacosDiscoveryServiceIP() {\n\t\tassertThat(registration.getHost()).isEqualTo(\"123.123.123.123\");\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@ImportAutoConfiguration({ AutoServiceRegistrationConfiguration.class,\n\t\t\tNacosDiscoveryClientConfiguration.class,\n\t\t\tNacosServiceRegistryAutoConfiguration.class })\n\tpublic static class TestConfig {\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/registry/NacosAutoServiceRegistrationManagementPortTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.registry;\n\nimport java.util.Properties;\nimport java.util.concurrent.Future;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration;\nimport com.alibaba.nacos.api.NacosFactory;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.listener.FuzzyWatchEventWatcher;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;\nimport org.springframework.context.annotation.Configuration;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;\n\n/**\n * @author xiaojing\n */\n\n@SpringBootTest(\n\t\tclasses = NacosAutoServiceRegistrationManagementPortTests.TestConfig.class,\n\t\tproperties = { \"spring.application.name=myTestService1\",\n\t\t\t\t\"management.server.port=8888\",\n\t\t\t\t\"management.server.servlet.context-path=/test-context-path\",\n\t\t\t\t\"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\",\n\t\t\t\t\"spring.cloud.nacos.discovery.port=8888\" },\n\t\twebEnvironment = RANDOM_PORT)\npublic class NacosAutoServiceRegistrationManagementPortTests {\n\n\t@Autowired\n\tprivate NacosRegistration registration;\n\n\t@Autowired\n\tprivate NacosAutoServiceRegistration nacosAutoServiceRegistration;\n\n\t@Autowired\n\tprivate NacosDiscoveryProperties properties;\n\n\tprivate static MockedStatic<NacosFactory> nacosFactoryMockedStatic;\n\tstatic {\n\t\tnacosFactoryMockedStatic = Mockito.mockStatic(NacosFactory.class);\n\t\tnacosFactoryMockedStatic.when(() -> NacosFactory.createNamingService((Properties) any()))\n\t\t\t\t.thenReturn(new MockNamingService() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void fuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void fuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic Future<ListView<String>> fuzzyWatchWithServiceKeys(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic Future<ListView<String>> fuzzyWatchWithServiceKeys(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void cancelFuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void cancelFuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\t\t\t\t});\n\t}\n\t@AfterAll\n\tpublic static void finished() {\n\t\tif (nacosFactoryMockedStatic != null) {\n\t\t\tnacosFactoryMockedStatic.close();\n\t\t}\n\t}\n\n\t@Test\n\tpublic void contextLoads() throws Exception {\n\t\tassertThat(registration).isNotNull();\n\t\tassertThat(properties).isNotNull();\n\t\tassertThat(nacosAutoServiceRegistration).isNotNull();\n\n\t\tcheckoutNacosDiscoveryManagementData();\n\t}\n\n\tprivate void checkoutNacosDiscoveryManagementData() {\n\t\tassertThat(properties.getMetadata().get(NacosRegistration.MANAGEMENT_PORT))\n\t\t\t\t.isEqualTo(\"8888\");\n\t\tassertThat(\n\t\t\t\tproperties.getMetadata().get(NacosRegistration.MANAGEMENT_CONTEXT_PATH))\n\t\t\t\t\t\t.isEqualTo(\"/test-context-path\");\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@ImportAutoConfiguration({ AutoServiceRegistrationConfiguration.class,\n\t\t\tNacosDiscoveryClientConfiguration.class,\n\t\t\tNacosServiceRegistryAutoConfiguration.class })\n\tpublic static class TestConfig {\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/registry/NacosAutoServiceRegistrationPortTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.registry;\n\nimport java.util.Properties;\nimport java.util.concurrent.Future;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration;\nimport com.alibaba.nacos.api.NacosFactory;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.listener.FuzzyWatchEventWatcher;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;\nimport org.springframework.context.annotation.Configuration;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;\n\n/**\n * @author xiaojing\n */\n\n@SpringBootTest(classes = NacosAutoServiceRegistrationPortTests.TestConfig.class,\n\t\tproperties = { \"spring.application.name=myTestService1\",\n\t\t\t\t\"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\",\n\t\t\t\t\"spring.cloud.nacos.discovery.port=8888\" },\n\t\twebEnvironment = RANDOM_PORT)\npublic class NacosAutoServiceRegistrationPortTests {\n\n\t@Autowired\n\tprivate NacosRegistration registration;\n\n\t@Autowired\n\tprivate NacosAutoServiceRegistration nacosAutoServiceRegistration;\n\n\t@Autowired\n\tprivate NacosDiscoveryProperties properties;\n\n\tprivate static MockedStatic<NacosFactory> nacosFactoryMockedStatic;\n\tstatic {\n\t\tnacosFactoryMockedStatic = Mockito.mockStatic(NacosFactory.class);\n\t\tnacosFactoryMockedStatic.when(() -> NacosFactory.createNamingService((Properties) any()))\n\t\t\t\t.thenReturn(new MockNamingService() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void fuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void fuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic Future<ListView<String>> fuzzyWatchWithServiceKeys(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic Future<ListView<String>> fuzzyWatchWithServiceKeys(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void cancelFuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void cancelFuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\t\t\t\t});\n\t}\n\t@AfterAll\n\tpublic static void finished() {\n\t\tif (nacosFactoryMockedStatic != null) {\n\t\t\tnacosFactoryMockedStatic.close();\n\t\t}\n\t}\n\n\t@Test\n\tpublic void contextLoads() throws Exception {\n\t\tassertThat(registration).isNotNull();\n\t\tassertThat(properties).isNotNull();\n\t\tassertThat(nacosAutoServiceRegistration).isNotNull();\n\n\t\tcheckoutNacosDiscoveryServicePort();\n\t}\n\n\tprivate void checkoutNacosDiscoveryServicePort() {\n\t\tassertThat(registration.getPort()).isEqualTo(8888);\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@ImportAutoConfiguration({ AutoServiceRegistrationConfiguration.class,\n\t\t\tNacosDiscoveryClientConfiguration.class,\n\t\t\tNacosServiceRegistryAutoConfiguration.class })\n\tpublic static class TestConfig {\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/registry/NacosAutoServiceRegistrationTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.registry;\n\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.Future;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.NacosServiceManager;\nimport com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration;\nimport com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpoint;\nimport com.alibaba.nacos.api.NacosFactory;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.listener.FuzzyWatchEventWatcher;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.boot.test.web.server.LocalServerPort;\nimport org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;\nimport org.springframework.cloud.commons.util.InetUtils;\nimport org.springframework.context.annotation.Configuration;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;\n\n/**\n * @author xiaojing\n */\n\n@SpringBootTest(classes = NacosAutoServiceRegistrationTests.TestConfig.class,\n\t\tproperties = { \"spring.application.name=myTestService1\",\n\t\t\t\t\"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\",\n\t\t\t\t\"spring.cloud.nacos.discovery.endpoint=test-endpoint\",\n\t\t\t\t\"spring.cloud.nacos.discovery.namespace=test-namespace\",\n\t\t\t\t\"spring.cloud.nacos.discovery.log-name=test-logName\",\n\t\t\t\t\"spring.cloud.nacos.discovery.weight=2\",\n\t\t\t\t\"spring.cloud.nacos.discovery.clusterName=test-cluster\",\n\t\t\t\t\"spring.cloud.nacos.discovery.namingLoadCacheAtStart=true\",\n\t\t\t\t\"spring.cloud.nacos.discovery.secure=true\",\n\t\t\t\t\"spring.cloud.nacos.discovery.accessKey=test-accessKey\",\n\t\t\t\t\"spring.cloud.nacos.discovery.ip=8.8.8.8\",\n\t\t\t\t\"spring.cloud.nacos.discovery.secretKey=test-secretKey\",\n\t\t\t\t\"spring.cloud.nacos.discovery.heart-beat-interval=3000\",\n\t\t\t\t\"spring.cloud.nacos.discovery.heart-beat-timeout=6000\",\n\t\t\t\t\"spring.cloud.nacos.discovery.ip-delete-timeout=9000\" },\n\t\twebEnvironment = RANDOM_PORT)\npublic class NacosAutoServiceRegistrationTests {\n\n\t@Autowired\n\tprivate NacosRegistration registration;\n\n\t@Autowired\n\tprivate NacosAutoServiceRegistration nacosAutoServiceRegistration;\n\n\t@LocalServerPort\n\tprivate int port;\n\n\t@Autowired\n\tprivate NacosDiscoveryProperties properties;\n\n\t@Autowired\n\tprivate NacosServiceManager nacosServiceManager;\n\n\t@Autowired\n\tprivate InetUtils inetUtils;\n\n\tprivate static MockedStatic<NacosFactory> nacosFactoryMockedStatic;\n\tstatic {\n\t\tnacosFactoryMockedStatic = Mockito.mockStatic(NacosFactory.class);\n\t\tnacosFactoryMockedStatic.when(() -> NacosFactory.createNamingService((Properties) any()))\n\t\t\t\t.thenReturn(new MockNamingService() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void fuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void fuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic Future<ListView<String>> fuzzyWatchWithServiceKeys(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic Future<ListView<String>> fuzzyWatchWithServiceKeys(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void cancelFuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void cancelFuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\t\t\t\t});\n\t}\n\t@AfterAll\n\tpublic static void finished() {\n\t\tif (nacosFactoryMockedStatic != null) {\n\t\t\tnacosFactoryMockedStatic.close();\n\t\t}\n\t}\n\n\t@Test\n\tpublic void contextLoads() throws Exception {\n\t\tassertThat(registration).isNotNull();\n\t\tassertThat(properties).isNotNull();\n\t\tassertThat(nacosAutoServiceRegistration).isNotNull();\n\n\t\tcheckoutNacosDiscoveryServerAddr();\n\t\tcheckoutNacosDiscoveryEndpoint();\n\t\tcheckoutNacosDiscoveryNamespace();\n\t\tcheckoutNacosDiscoveryLogName();\n\t\tcheckoutNacosDiscoveryWeight();\n\t\tcheckoutNacosDiscoveryClusterName();\n\t\tcheckoutNacosDiscoveryCache();\n\t\tcheckoutNacosDiscoverySecure();\n\t\tcheckoutNacosDiscoveryAccessKey();\n\t\tcheckoutNacosDiscoverySecrectKey();\n\t\tcheckoutNacosDiscoveryHeartBeatInterval();\n\t\tcheckoutNacosDiscoveryHeartBeatTimeout();\n\t\tcheckoutNacosDiscoveryIpDeleteTimeout();\n\n\t\tcheckoutNacosDiscoveryServiceName();\n\t\tcheckoutNacosDiscoveryServiceIP();\n\t\tcheckoutNacosDiscoveryServicePort();\n\n\t\tcheckAutoRegister();\n\n\t\tcheckoutEndpoint();\n\n\t}\n\n\tprivate void checkAutoRegister() {\n\t\tassertThat(nacosAutoServiceRegistration.isRunning()).isEqualTo(Boolean.TRUE);\n\t}\n\n\tprivate void checkoutNacosDiscoveryServerAddr() {\n\t\tassertThat(properties.getServerAddr()).isEqualTo(\"127.0.0.1:8848\");\n\t}\n\n\tprivate void checkoutNacosDiscoveryEndpoint() {\n\t\tassertThat(properties.getEndpoint()).isEqualTo(\"test-endpoint\");\n\t}\n\n\tprivate void checkoutNacosDiscoveryNamespace() {\n\t\tassertThat(properties.getNamespace()).isEqualTo(\"test-namespace\");\n\t}\n\n\tprivate void checkoutNacosDiscoveryLogName() {\n\t\tassertThat(properties.getLogName()).isEqualTo(\"test-logName\");\n\t}\n\n\tprivate void checkoutNacosDiscoveryWeight() {\n\t\tassertThat(properties.getWeight()).isEqualTo(2);\n\t}\n\n\tprivate void checkoutNacosDiscoveryClusterName() {\n\t\tassertThat(properties.getClusterName()).isEqualTo(\"test-cluster\");\n\t}\n\n\tprivate void checkoutNacosDiscoveryCache() {\n\t\tassertThat(properties.getNamingLoadCacheAtStart()).isEqualTo(\"true\");\n\t}\n\n\tprivate void checkoutNacosDiscoverySecure() {\n\t\tassertThat(properties.isSecure()).isEqualTo(true);\n\t\tassertThat(properties.getMetadata().get(\"secure\")).isEqualTo(\"true\");\n\t}\n\n\tprivate void checkoutNacosDiscoveryAccessKey() {\n\t\tassertThat(properties.getAccessKey()).isEqualTo(\"test-accessKey\");\n\t}\n\n\tprivate void checkoutNacosDiscoverySecrectKey() {\n\t\tassertThat(properties.getSecretKey()).isEqualTo(\"test-secretKey\");\n\t}\n\n\tprivate void checkoutNacosDiscoveryHeartBeatInterval() {\n\t\tassertThat(properties.getHeartBeatInterval()).isEqualTo(Integer.valueOf(3000));\n\t}\n\n\tprivate void checkoutNacosDiscoveryHeartBeatTimeout() {\n\t\tassertThat(properties.getHeartBeatTimeout()).isEqualTo(Integer.valueOf(6000));\n\t}\n\n\tprivate void checkoutNacosDiscoveryIpDeleteTimeout() {\n\t\tassertThat(properties.getIpDeleteTimeout()).isEqualTo(Integer.valueOf(9000));\n\t}\n\n\tprivate void checkoutNacosDiscoveryServiceName() {\n\t\tassertThat(properties.getService()).isEqualTo(\"myTestService1\");\n\t}\n\n\tprivate void checkoutNacosDiscoveryServiceIP() {\n\t\tassertThat(registration.getHost()).isEqualTo(\"8.8.8.8\");\n\t}\n\n\tprivate void checkoutNacosDiscoveryServicePort() {\n\t\tassertThat(registration.getPort()).isEqualTo(port);\n\t}\n\n\tprivate void checkoutEndpoint() throws Exception {\n\t\tNacosDiscoveryEndpoint nacosDiscoveryEndpoint = new NacosDiscoveryEndpoint(\n\t\t\t\tnacosServiceManager, properties);\n\t\tMap<String, Object> map = nacosDiscoveryEndpoint.nacosDiscovery();\n\n\t\tassertThat(properties).isEqualTo(map.get(\"NacosDiscoveryProperties\"));\n\t\t// assertThat(properties.namingServiceInstance().getSubscribeServices().toString())\n\t\t// .isEqualTo(map.get(\"subscribe\").toString());\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@ImportAutoConfiguration({ AutoServiceRegistrationConfiguration.class,\n\t\t\tNacosDiscoveryClientConfiguration.class,\n\t\t\tNacosServiceRegistryAutoConfiguration.class })\n\tpublic static class TestConfig {\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/registry/NacosGracefulShutdownDelegateTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.registry;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.event.ContextClosedEvent;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n/**\n * @author <a href=\"mailto:uuuyuqi@gmail.com\">uuuyuqi</a>\n */\n@ExtendWith(MockitoExtension.class)\npublic class NacosGracefulShutdownDelegateTests {\n\n\t@Mock\n\tprivate NacosAutoServiceRegistration autoServiceRegistration;\n\n\t@Mock\n\tprivate NacosDiscoveryProperties nacosDiscoveryProperties;\n\n\t@Mock\n\tprivate ApplicationContext applicationContext;\n\n\t@InjectMocks\n\tprivate NacosGracefulShutdownDelegate delegate;\n\n\t@BeforeEach\n\tvoid setUp() {\n\t\tdelegate.setApplicationContext(applicationContext);\n\t}\n\n\t@Test\n\tpublic void sameContextShouldTriggerStop() {\n\t\twhen(nacosDiscoveryProperties.getGracefulShutdownWaitTime()).thenReturn(0);\n\n\t\tdelegate.onApplicationEvent(new ContextClosedEvent(applicationContext));\n\n\t\tverify(autoServiceRegistration).stop();\n\t}\n\n\t@Test\n\tpublic void differentContextShouldNotTriggerStop() {\n\t\tdelegate.onApplicationEvent(new ContextClosedEvent(Mockito.mock(ApplicationContext.class)));\n\n\t\tverify(autoServiceRegistration, never()).stop();\n\t}\n\n\t@Test\n\tpublic void stopExceptionShouldBeSwallowed() {\n\t\tdoThrow(new RuntimeException(\"boom\")).when(autoServiceRegistration).stop();\n\n\t\tdelegate.onApplicationEvent(new ContextClosedEvent(applicationContext));\n\n\t\tverify(autoServiceRegistration).stop();\n\t}\n\n\t@Test\n\tpublic void supportsAsyncExecutionShouldBeFalse() {\n\t\tassertThat(delegate.supportsAsyncExecution()).isFalse();\n\t}\n}\n\n\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/registry/NacosRegistrationCustomizerTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.registry;\n\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.Future;\n\nimport com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration;\nimport com.alibaba.nacos.api.NacosFactory;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.listener.FuzzyWatchEventWatcher;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\nimport static org.assertj.core.api.Assertions.assertThat; // 导入 AssertJ 的断言\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;\n\n/**\n * @author L.cm\n */\n@SpringBootTest(classes = NacosRegistrationCustomizerTest.TestConfig.class,\n\t\tproperties = { \"spring.application.name=myTestService1\",\n\t\t\t\t\"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\" },\n\t\twebEnvironment = RANDOM_PORT)\npublic class NacosRegistrationCustomizerTest {\n\n\t@Autowired\n\tprivate NacosAutoServiceRegistration nacosAutoServiceRegistration;\n\n\tprivate static MockedStatic<NacosFactory> nacosFactoryMockedStatic;\n\tstatic {\n\t\tnacosFactoryMockedStatic = Mockito.mockStatic(NacosFactory.class);\n\t\tnacosFactoryMockedStatic.when(() -> NacosFactory.createNamingService((Properties) any()))\n\t\t\t\t.thenReturn(new MockNamingService() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void fuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void fuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic Future<ListView<String>> fuzzyWatchWithServiceKeys(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic Future<ListView<String>> fuzzyWatchWithServiceKeys(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void cancelFuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void cancelFuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n\n\t\t\t\t\t}\n\t\t\t\t});\n\t}\n\t@AfterAll\n\tpublic static void finished() {\n\t\tif (nacosFactoryMockedStatic != null) {\n\t\t\tnacosFactoryMockedStatic.close();\n\t\t}\n\t}\n\n\n\t@Test\n\tpublic void contextLoads() throws Exception {\n\t\tNacosRegistration registration = nacosAutoServiceRegistration.getRegistration();\n\t\tMap<String, String> metadata = registration.getMetadata();\n\t\tassertThat(metadata.get(\"test1\")).isEqualTo(\"test1\");\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@ImportAutoConfiguration({ AutoServiceRegistrationConfiguration.class,\n\t\t\tNacosDiscoveryClientConfiguration.class,\n\t\t\tNacosServiceRegistryAutoConfiguration.class })\n\tpublic static class TestConfig {\n\n\t\t@Bean\n\t\tpublic NacosRegistrationCustomizer nacosRegistrationCustomizer() {\n\t\t\treturn registration -> {\n\t\t\t\tMap<String, String> metadata = registration.getMetadata();\n\t\t\t\tmetadata.put(\"test1\", \"test1\");\n\t\t\t};\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/test/CommonTestConfig.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.test;\n\nimport org.springframework.cloud.client.loadbalancer.LoadBalanced;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author xiaojing\n */\n\n@Configuration\npublic class CommonTestConfig {\n\n\t@Bean\n\t@LoadBalanced\n\tRestTemplate loadBalancedRestTemplate() {\n\t\treturn new RestTemplate();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/test/NacosMockTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.nacos.test;\n\nimport java.util.Map;\nimport java.util.UUID;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\n\n/**\n * @author xiaojing\n */\npublic final class NacosMockTest {\n\n\tprivate NacosMockTest() {\n\n\t}\n\n\tpublic static Instance serviceInstance(String serviceName, boolean isHealthy,\n\t\t\tMap<String, String> metadata) {\n\t\tInstance instance = new Instance();\n\t\tinstance.setInstanceId(UUID.randomUUID().toString());\n\t\tinstance.setServiceName(serviceName);\n\t\tinstance.setHealthy(isHealthy);\n\t\tinstance.setMetadata(metadata);\n\t\treturn instance;\n\t}\n\n\tpublic static Instance serviceInstance(String serviceName, boolean isHealthy,\n\t\t\tString host, int port, Map<String, String> metadata) {\n\t\tInstance instance = new Instance();\n\t\tinstance.setIp(host);\n\t\tinstance.setPort(port);\n\t\tinstance.setServiceName(serviceName);\n\t\tinstance.setHealthy(isHealthy);\n\t\tinstance.setMetadata(metadata);\n\t\treturn instance;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-starters</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n    <artifactId>spring-cloud-starter-alibaba-schedulerx</artifactId>\n    <name>Spring Cloud Starter Alibaba Scheduling</name>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-jdbc</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <!--spring boot-->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-autoconfigure</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>junit</groupId>\n            <artifactId>junit</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>jakarta.annotation</groupId>\n            <artifactId>jakarta.annotation-api</artifactId>\n        </dependency>\n\n        <!-- schedulerx dependency -->\n        <dependency>\n            <groupId>com.aliyun.schedulerx</groupId>\n            <artifactId>schedulerx2-worker</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.aliyun</groupId>\n            <artifactId>aliyun-java-sdk-schedulerx2</artifactId>\n            <version>1.1.0</version>\n        </dependency>\n\n        <dependency>\n            <groupId>com.aliyun</groupId>\n            <artifactId>aliyun-java-sdk-core</artifactId>\n            <version>4.4.6</version>\n        </dependency>\n        <!-- schedulerx dependency end-->\n\n        <!-- shedlock dependency -->\n        <dependency>\n            <groupId>net.javacrumbs.shedlock</groupId>\n            <artifactId>shedlock-spring</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>net.javacrumbs.shedlock</groupId>\n            <artifactId>shedlock-provider-jdbc-template</artifactId>\n        </dependency>\n        <!-- shedlock dependency end -->\n    </dependencies>\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/java/com/alibaba/cloud/scheduling/SchedulingConstants.java",
    "content": "/*\n * Copyright 2024-present the original author or 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\npackage com.alibaba.cloud.scheduling;\n\n/**\n * @author yaohui\n **/\npublic final class SchedulingConstants {\n\n\t/**\n\t * Scheduling config prefix.\n\t */\n\tpublic static final String SCHEDULING_CONFIG_PREFIX = \"spring.cloud.scheduling\";\n\n\t/**\n\t * Scheduling distributed mode.\n\t */\n\tpublic static final String SCHEDULING_CONFIG_DISTRIBUTED_MODE_KEY = SCHEDULING_CONFIG_PREFIX + \".distributed-mode\";\n\n\tprivate SchedulingConstants() {\n\t\tthrow new AssertionError(\"Must not instantiate constant utility class\");\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/java/com/alibaba/cloud/scheduling/schedulerx/JobProperty.java",
    "content": "/*\n * Copyright 2024-present the original author or 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\npackage com.alibaba.cloud.scheduling.schedulerx;\n\nimport com.alibaba.schedulerx.common.domain.ExecuteMode;\nimport com.alibaba.schedulerx.common.domain.JobType;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\n\n/**\n * Job property.\n *\n * @author xiaomeng.hxm\n */\n@ConfigurationProperties(prefix = SchedulerxProperties.CONFIG_PREFIX)\npublic final class JobProperty {\n\n\tprivate String jobName;\n\n\tprivate String jobType = JobType.JAVA.getKey();\n\n\tprivate String jobModel = ExecuteMode.STANDALONE.getKey();\n\n\tprivate String className;\n\n\tprivate String content;\n\n\tprivate Integer timeType;\n\n\tprivate String timeExpression;\n\n\tprivate String cron;\n\n\tprivate String oneTime;\n\n\tprivate String jobParameter;\n\n\tprivate String description;\n\n\tprivate boolean overwrite = false;\n\n\tpublic String getJobType() {\n\t\treturn jobType;\n\t}\n\n\tpublic void setJobType(String jobType) {\n\t\tthis.jobType = jobType;\n\t}\n\n\tpublic String getJobModel() {\n\t\treturn jobModel;\n\t}\n\n\tpublic void setJobModel(String jobModel) {\n\t\tthis.jobModel = jobModel;\n\t}\n\n\tpublic String getClassName() {\n\t\treturn className;\n\t}\n\n\tpublic void setClassName(String className) {\n\t\tthis.className = className;\n\t}\n\n\tpublic String getCron() {\n\t\treturn cron;\n\t}\n\n\tpublic void setCron(String cron) {\n\t\tthis.cron = cron;\n\t}\n\n\tpublic String getOneTime() {\n\t\treturn oneTime;\n\t}\n\n\tpublic void setOneTime(String oneTime) {\n\t\tthis.oneTime = oneTime;\n\t}\n\n\tpublic String getJobParameter() {\n\t\treturn jobParameter;\n\t}\n\n\tpublic void setJobParameter(String jobParameter) {\n\t\tthis.jobParameter = jobParameter;\n\t}\n\n\tpublic String getDescription() {\n\t\treturn description;\n\t}\n\n\tpublic void setDescription(String description) {\n\t\tthis.description = description;\n\t}\n\n\tpublic boolean isOverwrite() {\n\t\treturn overwrite;\n\t}\n\n\tpublic void setOverwrite(boolean overwrite) {\n\t\tthis.overwrite = overwrite;\n\t}\n\n\tpublic String getContent() {\n\t\treturn content;\n\t}\n\n\tpublic void setContent(String content) {\n\t\tthis.content = content;\n\t}\n\n\tpublic String getJobName() {\n\t\treturn jobName;\n\t}\n\n\tpublic void setJobName(String jobName) {\n\t\tthis.jobName = jobName;\n\t}\n\n\tpublic Integer getTimeType() {\n\t\treturn timeType;\n\t}\n\n\tpublic void setTimeType(Integer timeType) {\n\t\tthis.timeType = timeType;\n\t}\n\n\tpublic String getTimeExpression() {\n\t\treturn timeExpression;\n\t}\n\n\tpublic void setTimeExpression(String timeExpression) {\n\t\tthis.timeExpression = timeExpression;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/java/com/alibaba/cloud/scheduling/schedulerx/SchedulerxAutoConfigure.java",
    "content": "/*\n * Copyright 2024-present the original author or 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\npackage com.alibaba.cloud.scheduling.schedulerx;\n\nimport com.alibaba.cloud.scheduling.SchedulingConstants;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.context.annotation.Import;\n\n/**\n * schedulerx2 starter.\n *\n * @author yaohui\n **/\n@EnableConfigurationProperties(SchedulerxProperties.class)\n@ConditionalOnProperty(name = SchedulingConstants.SCHEDULING_CONFIG_DISTRIBUTED_MODE_KEY, havingValue = \"schedulerx\")\n@Import({SchedulerxConfigurations.SchedulerxWorkerConfiguration.class,\n\t\tSchedulerxConfigurations.SpringScheduleAdaptConfiguration.class})\npublic class SchedulerxAutoConfigure {\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/java/com/alibaba/cloud/scheduling/schedulerx/SchedulerxConfigurations.java",
    "content": "/*\n * Copyright 2024-present the original author or 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\npackage com.alibaba.cloud.scheduling.schedulerx;\n\nimport com.alibaba.cloud.scheduling.schedulerx.service.JobSyncService;\nimport com.alibaba.cloud.scheduling.schedulerx.service.ScheduledJobSyncConfigurer;\nimport com.alibaba.schedulerx.common.util.ConfigUtil;\nimport com.alibaba.schedulerx.common.util.StringUtils;\nimport com.alibaba.schedulerx.worker.SchedulerxWorker;\nimport com.alibaba.schedulerx.worker.domain.WorkerConstants;\nimport com.alibaba.schedulerx.worker.log.LogFactory;\nimport com.alibaba.schedulerx.worker.log.Logger;\nimport com.alibaba.schedulerx.worker.processor.springscheduling.NoOpScheduler;\nimport com.alibaba.schedulerx.worker.processor.springscheduling.SchedulerxAnnotationBeanPostProcessor;\nimport com.alibaba.schedulerx.worker.processor.springscheduling.SchedulerxSchedulingConfigurer;\nimport jakarta.annotation.PostConstruct;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.AutoConfigureAfter;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor;\n\n/**\n * @author yaohui\n **/\npublic class SchedulerxConfigurations {\n\n\t@Configuration(proxyBeanMethods = false)\n\t@ConditionalOnClass(SchedulerxWorker.class)\n\t@ConditionalOnProperty(prefix = SchedulerxProperties.CONFIG_PREFIX, name = \"enabled\", havingValue = \"true\", matchIfMissing = true)\n\tstatic class SchedulerxWorkerConfiguration {\n\n\t\tprivate static final Logger LOGGER = LogFactory.getLogger(SchedulerxAutoConfigure.class);\n\n\t\tprivate static final String WORKER_STARTER_SPRING_CLOUD = \"springcloud\";\n\n\t\t@Autowired\n\t\tprivate SchedulerxProperties properties;\n\n\t\t@Bean\n\t\tpublic JobSyncService jobSyncService() {\n\t\t\treturn new JobSyncService();\n\t\t}\n\n\t\t@PostConstruct\n\t\tpublic void syncJobs() throws Exception {\n\t\t\tif (!properties.getJobs().isEmpty()) {\n\t\t\t\tLOGGER.info(\"{}.jobs is not empty, start to sync jobs...\", SchedulerxProperties.CONFIG_PREFIX);\n\t\t\t\tjobSyncService().syncJobs();\n\t\t\t\tLOGGER.info(\"sync jobs finished.\");\n\t\t\t}\n\t\t}\n\n\t\t@Bean\n\t\tpublic SchedulerxWorker schedulerxWorker() {\n\t\t\tSchedulerxWorker schedulerxWorker = new SchedulerxWorker();\n\t\t\tschedulerxWorker.setDomainName(properties.getDomainName());\n\t\t\tschedulerxWorker.setGroupId(properties.getGroupId());\n\t\t\tschedulerxWorker.setEnableBatchWork(properties.isEnableBatchWork());\n\t\t\tschedulerxWorker.setDisableSites(properties.getDisableSites());\n\t\t\tschedulerxWorker.setEnableSites(properties.getEnableSites());\n\t\t\tschedulerxWorker.setDisableUnits(properties.getDisableUnits());\n\t\t\tschedulerxWorker.setEnableUnits(properties.getEnableUnits());\n\t\t\tschedulerxWorker.setAppKey(properties.getAppKey());\n\t\t\tschedulerxWorker.setAliyunAccessKey(properties.getAliyunAccessKey());\n\t\t\tschedulerxWorker.setAliyunSecretKey(properties.getAliyunSecretKey());\n\t\t\tschedulerxWorker.setNamespace(properties.getNamespace());\n\t\t\tschedulerxWorker.setHost(properties.getHost());\n\t\t\tschedulerxWorker.setPort(properties.getPort());\n\t\t\tschedulerxWorker.setEndpoint(properties.getEndpoint());\n\t\t\tschedulerxWorker.setNamespaceSource(properties.getNamespaceSource());\n\t\t\tschedulerxWorker.setMaxTaskBodySize(properties.getMaxTaskBodySize());\n\t\t\tschedulerxWorker.setBlockAppStart(properties.isBlockAppStart());\n\t\t\tschedulerxWorker.setSTSAccessKey(properties.getStsAccessKey());\n\t\t\tschedulerxWorker.setSTSSecretKey(properties.getStsSecretKey());\n\t\t\tschedulerxWorker.setSTSSecretToken(properties.getStsToken());\n\t\t\tschedulerxWorker.setSlsCollectorEnable(properties.isSlsCollectorEnable());\n\t\t\tschedulerxWorker.setShareContainerPool(properties.isShareContainerPool());\n\t\t\tschedulerxWorker.setThreadPoolMode(properties.getThreadPoolMode());\n\t\t\tschedulerxWorker.setLabel(properties.getLabel());\n\t\t\tschedulerxWorker.setLabelPath(properties.getLabelPath());\n\t\t\tif (properties.isShareContainerPool() || WorkerConstants.THREAD_POOL_MODE_ALL.equals(properties.getThreadPoolMode())) {\n\t\t\t\tschedulerxWorker.setSharePoolSize(properties.getSharePoolSize());\n\t\t\t\tschedulerxWorker.setSharePoolQueueSize(properties.getSharePoolQueueSize());\n\t\t\t}\n\t\t\tif (StringUtils.isNotEmpty(properties.getEndpointPort())) {\n\t\t\t\tschedulerxWorker.setEndpointPort(Integer.parseInt(properties.getEndpointPort()));\n\t\t\t}\n\t\t\tschedulerxWorker.setEnableCgroupMetrics(properties.isEnableCgroupMetrics());\n\t\t\tif (properties.isEnableCgroupMetrics()) {\n\t\t\t\tschedulerxWorker.setCgroupPathPrefix(properties.getCgroupPathPrefix());\n\t\t\t}\n\t\t\tif (StringUtils.isNotEmpty(properties.getNamespaceSource())) {\n\t\t\t\tschedulerxWorker.setNamespaceSource(properties.getNamespaceSource());\n\t\t\t}\n\t\t\tschedulerxWorker.setAkkaRemotingAutoRecover(properties.isAkkaRemotingAutoRecover());\n\t\t\tschedulerxWorker.setEnableHeartbeatLog(properties.isEnableHeartbeatLog());\n\t\t\tschedulerxWorker.setMapMasterStatusCheckInterval(properties.getMapMasterStatusCheckInterval());\n\t\t\tschedulerxWorker.setEnableSecondDelayCycleIntervalMs(properties.isEnableSecondDelayCycleIntervalMs());\n\t\t\tschedulerxWorker.setEnableMapMasterFailover(properties.isEnableMapMasterFailover());\n\t\t\tschedulerxWorker.setEnableSecondDelayStandaloneDispatch(properties.isEnableSecondDelayStandaloneDispatch());\n\t\t\tschedulerxWorker.setPageSize(properties.getPageSize());\n\t\t\tschedulerxWorker.setGraceShutdownMode(properties.getGraceShutdownMode());\n\t\t\tif (properties.getGraceShutdownTimeout() > 0) {\n\t\t\t\tschedulerxWorker.setGraceShutdownTimeout(properties.getGraceShutdownTimeout());\n\t\t\t}\n\t\t\tschedulerxWorker.setBroadcastDispatchThreadNum(properties.getBroadcastDispatchThreadNum());\n\t\t\tschedulerxWorker.setBroadcastDispatchThreadEnable(properties.isBroadcastDispatchThreadEnable());\n\t\t\tschedulerxWorker.setBroadcastMasterExecEnable(properties.isBroadcastMasterExecEnable());\n\t\t\tschedulerxWorker.setBroadcastDispatchRetryTimes(properties.getBroadcastDispatchRetryTimes());\n\t\t\tschedulerxWorker.setProcessorPoolSize(properties.getProcessorPoolSize());\n\t\t\tschedulerxWorker.setMapMasterDispatchRandom(properties.isMapMasterDispatchRandom());\n\t\t\tschedulerxWorker.setMapMasterRouterStrategy(properties.getMapMasterRouterStrategy());\n\t\t\tif (StringUtils.isNotEmpty(properties.getH2DatabaseUser())) {\n\t\t\t\tschedulerxWorker.setH2DatabaseUser(properties.getH2DatabaseUser());\n\t\t\t}\n\t\t\tif (StringUtils.isNotEmpty(properties.getH2DatabasePassword())) {\n\t\t\t\tschedulerxWorker.setH2DatabasePassword(properties.getH2DatabasePassword());\n\t\t\t}\n\t\t\tschedulerxWorker.setHttpServerEnable(properties.getHttpServerEnable());\n\t\t\tschedulerxWorker.setHttpServerPort(properties.getHttpServerPort());\n\t\t\tif (properties.getMaxMapDiskPercent() != null) {\n\t\t\t\tschedulerxWorker.setMaxMapDiskPercent(properties.getMaxMapDiskPercent());\n\t\t\t}\n\n\t\t\tConfigUtil.getWorkerConfig().setProperty(WorkerConstants.WORKER_STARTER_MODE,\n\t\t\t\t\tWORKER_STARTER_SPRING_CLOUD);\n\t\t\treturn schedulerxWorker;\n\t\t}\n\t}\n\n\n\t@Configuration(proxyBeanMethods = false)\n\t@AutoConfigureAfter(SchedulerxWorkerConfiguration.class)\n\t@ConditionalOnBean(SchedulerxWorker.class)\n\tstatic class SpringScheduleAdaptConfiguration {\n\n\t\t@Bean(ScheduledAnnotationBeanPostProcessor.DEFAULT_TASK_SCHEDULER_BEAN_NAME)\n\t\tpublic NoOpScheduler noOpScheduler() {\n\t\t\treturn new NoOpScheduler();\n\t\t}\n\n\t\t@Bean\n\t\tpublic SchedulerxSchedulingConfigurer schedulerxSchedulingConfigurer() {\n\t\t\treturn new SchedulerxSchedulingConfigurer(noOpScheduler(), true);\n\t\t}\n\n\t\t@Bean\n\t\tpublic static SchedulerxAnnotationBeanPostProcessor schedulerxAnnotationBeanPostProcessor() {\n\t\t\treturn new SchedulerxAnnotationBeanPostProcessor();\n\t\t}\n\n\t\t@Bean\n\t\t@ConditionalOnProperty(prefix = SchedulerxProperties.CONFIG_PREFIX, name = \"task-sync\", havingValue = \"true\")\n\t\tpublic ScheduledJobSyncConfigurer scheduledJobSyncConfigurer() {\n\t\t\treturn new ScheduledJobSyncConfigurer();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/java/com/alibaba/cloud/scheduling/schedulerx/SchedulerxProperties.java",
    "content": "/*\n * Copyright 2024-present the original author or 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\npackage com.alibaba.cloud.scheduling.schedulerx;\n\nimport java.util.HashMap;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\nimport com.alibaba.cloud.scheduling.SchedulingConstants;\nimport com.alibaba.schedulerx.common.domain.ContactInfo;\nimport com.alibaba.schedulerx.common.util.JsonUtil;\nimport com.alibaba.schedulerx.worker.domain.WorkerConstants;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.boot.context.properties.ConfigurationProperties;\n\n/**\n * schedulerx worker properties.\n *\n * @author yaohui\n **/\n@ConfigurationProperties(prefix = SchedulerxProperties.CONFIG_PREFIX)\npublic class SchedulerxProperties implements InitializingBean {\n\n\tprivate static final Logger logger = LoggerFactory.getLogger(SchedulerxProperties.class);\n\n\t/**\n\t * schedulerx config prefix.\n\t */\n\tpublic static final String CONFIG_PREFIX = SchedulingConstants.SCHEDULING_CONFIG_PREFIX + \".schedulerx\";\n\n\t/**\n\t * domainName.\n\t */\n\tprivate String domainName;\n\n\t/**\n\t * groupId.\n\t */\n\tprivate String groupId;\n\n\t/**\n\t * host.\n\t */\n\tprivate String host;\n\n\t/**\n\t * client port.\n\t */\n\tprivate int port = 0;\n\n\tprivate String enableUnits;\n\n\tprivate String disableUnits;\n\n\tprivate String enableSites;\n\n\tprivate String disableSites;\n\n\tprivate boolean enableBatchWork;\n\n\t/**\n\t * enabled: true; false.\n\t */\n\tprivate boolean enabled = true;\n\n\t/**\n\t * appName.\n\t */\n\tprivate String appName;\n\n\t/**\n\t * appKey.\n\t */\n\tprivate String appKey;\n\n\t/**\n\t * aliyunRamRole.\n\t */\n\tprivate String aliyunRamRole;\n\n\t/**\n\t * aliyunAccessKey.\n\t */\n\tprivate String aliyunAccessKey;\n\t/**\n\t * aliyunSecretKey.\n\t */\n\tprivate String aliyunSecretKey;\n\n\t/**\n\t * STS ak.\n\t */\n\tprivate String stsAccessKey;\n\n\t/**\n\t * STS sk.\n\t */\n\tprivate String stsSecretKey;\n\n\t/**\n\t * STS secret token.\n\t */\n\tprivate String stsToken;\n\n\t/**\n\t * Namespace UID.\n\t */\n\tprivate String namespace;\n\n\t/**\n\t * endpoint.\n\t */\n\tprivate String endpoint;\n\n\t/**\n\t * endpointPort.\n\t */\n\tprivate String endpointPort;\n\n\t/**\n\t * namespaceName.\n\t */\n\tprivate String namespaceName;\n\n\t/**\n\t * namespaceSource.\n\t */\n\tprivate String namespaceSource;\n\n\t/**\n\t * maxTaskBodySize (byte).\n\t */\n\tprivate int maxTaskBodySize = WorkerConstants.TASK_BODY_SIZE_MAX_DEFAULT;\n\n\tprivate boolean blockAppStart = true;\n\n\t/**\n\t * slsCollectorEnable.\n\t */\n\tprivate boolean slsCollectorEnable = true;\n\n\t/**\n\t * shareContainerPool.\n\t */\n\tprivate boolean shareContainerPool = false;\n\n\t/**\n\t * threadPoolMode.\n\t */\n\tprivate String threadPoolMode;\n\n\t/**\n\t * sharePoolSize.\n\t */\n\tprivate int sharePoolSize = WorkerConstants.SHARE_POOL_SIZE_DEFAULT;\n\n\t/**\n\t * sharePoolQueueSize.\n\t */\n\tprivate int sharePoolQueueSize = Integer.MAX_VALUE;\n\n\t/**\n\t * Wlabel.\n\t */\n\tprivate String label;\n\n\tprivate String labelPath = \"/etc/podinfo/labels\";\n\n\t/**\n\t * enableCgroupMetrics.\n\t */\n\tprivate boolean enableCgroupMetrics = false;\n\n\t/**\n\t * cgroupPathPrefix.\n\t */\n\tprivate String cgroupPathPrefix = \"/sys/fs/cgroup/cpu/\";\n\n\t/**\n\t * akkaRemotingAutoRecover.\n\t */\n\tprivate boolean akkaRemotingAutoRecover = true;\n\n\t/**\n\t * enableHeartbeatLog.\n\t */\n\tprivate boolean enableHeartbeatLog = true;\n\n\t/**\n\t * mapMasterStatusCheckInterval(ms).\n\t */\n\tprivate int mapMasterStatusCheckInterval = WorkerConstants.Map_MASTER_STATUS_CHECK_INTERVAL_DEFAULT;\n\n\t/**\n\t * enableSecondDelayCycleIntervalMs.\n\t */\n\tprivate boolean enableSecondDelayCycleIntervalMs = false;\n\n\t/**\n\t * enableMapMasterFailover.\n\t */\n\tprivate boolean enableMapMasterFailover = true;\n\n\t/**\n\t * enableSecondDelayStandaloneDispatch.\n\t */\n\tprivate boolean enableSecondDelayStandaloneDispatch = false;\n\n\t/**\n\t * pageSize.\n\t */\n\tprivate int pageSize = 1000;\n\n\t/**\n\t * GraceShutdownMode(WAIT_ALL; WAIT_RUNNING;).\n\t */\n\tprivate String graceShutdownMode;\n\n\t/**\n\t * graceShutdownTimeout.\n\t */\n\tprivate long graceShutdownTimeout = WorkerConstants.GRACE_SHUTDOWN_TIMEOUT_DEFAULT;\n\n\t/**\n\t * broadcastDispatchThreadNum.\n\t */\n\tprivate int broadcastDispatchThreadNum = 4;\n\n\t/**\n\t * broadcastDispatchRetryTimes.\n\t */\n\tprivate int broadcastDispatchRetryTimes = 1;\n\n\t/**\n\t * broadcastDispatchThreadEnable.\n\t */\n\tprivate boolean broadcastDispatchThreadEnable = false;\n\n\t/**\n\t * broadcastMasterExecEnable.\n\t */\n\tprivate boolean broadcastMasterExecEnable = true;\n\n\t/**\n\t * mapMasterDispatchRandom.\n\t */\n\tprivate boolean mapMasterDispatchRandom = false;\n\n\tprivate Integer mapMasterRouterStrategy;\n\n\tprivate String regionId;\n\n\t/**\n\t * h2DatabaseUser.\n\t */\n\tprivate String h2DatabaseUser;\n\n\t/**\n\t * h2DatabasePassword.\n\t */\n\tprivate String h2DatabasePassword;\n\n\t/**\n\t * httpServerEnable.\n\t */\n\tprivate Boolean httpServerEnable;\n\n\t/**\n\t * httpServerPort.\n\t */\n\tprivate Integer httpServerPort;\n\n\t/**\n\t * maxMapDiskPercent.\n\t */\n\tprivate Float maxMapDiskPercent;\n\n\tprivate Map<String, JobProperty> jobs = new LinkedHashMap<>();\n\n\tprivate String alarmChannel;\n\n\tprivate Map<String, ContactInfo> alarmUsers = new LinkedHashMap<>();\n\n\tprivate Map<String, Integer> processorPoolSize = new HashMap<>();\n\n\tpublic String getDomainName() {\n\t\treturn domainName;\n\t}\n\n\tpublic void setDomainName(String domainName) {\n\t\tthis.domainName = domainName;\n\t}\n\n\tpublic String getGroupId() {\n\t\treturn groupId;\n\t}\n\n\tpublic void setGroupId(String groupId) {\n\t\tthis.groupId = groupId;\n\t}\n\n\tpublic boolean isEnabled() {\n\t\treturn enabled;\n\t}\n\n\tpublic void setEnabled(boolean enabled) {\n\t\tthis.enabled = enabled;\n\t}\n\n\tpublic String getHost() {\n\t\treturn host;\n\t}\n\n\tpublic void setHost(String host) {\n\t\tthis.host = host;\n\t}\n\n\tpublic int getPort() {\n\t\treturn port;\n\t}\n\n\tpublic void setPort(int port) {\n\t\tthis.port = port;\n\t}\n\n\tpublic String getEnableUnits() {\n\t\treturn enableUnits;\n\t}\n\n\tpublic void setEnableUnits(String enableUnits) {\n\t\tthis.enableUnits = enableUnits;\n\t}\n\n\tpublic String getDisableUnits() {\n\t\treturn disableUnits;\n\t}\n\n\tpublic void setDisableUnits(String disableUnits) {\n\t\tthis.disableUnits = disableUnits;\n\t}\n\n\tpublic String getEnableSites() {\n\t\treturn enableSites;\n\t}\n\n\tpublic void setEnableSites(String enableSites) {\n\t\tthis.enableSites = enableSites;\n\t}\n\n\tpublic String getDisableSites() {\n\t\treturn disableSites;\n\t}\n\n\tpublic void setDisableSites(String disableSites) {\n\t\tthis.disableSites = disableSites;\n\t}\n\n\tpublic boolean isEnableBatchWork() {\n\t\treturn enableBatchWork;\n\t}\n\n\tpublic void setEnableBatchWork(boolean enableBatchWork) {\n\t\tthis.enableBatchWork = enableBatchWork;\n\t}\n\n\tpublic String getAliyunAccessKey() {\n\t\treturn aliyunAccessKey;\n\t}\n\n\tpublic void setAliyunAccessKey(String aliyunAccessKey) {\n\t\tthis.aliyunAccessKey = aliyunAccessKey;\n\t}\n\n\tpublic String getAliyunSecretKey() {\n\t\treturn aliyunSecretKey;\n\t}\n\n\tpublic void setAliyunSecretKey(String aliyunSecretKey) {\n\t\tthis.aliyunSecretKey = aliyunSecretKey;\n\t}\n\n\tpublic String getNamespace() {\n\t\treturn namespace;\n\t}\n\n\tpublic void setNamespace(String namespace) {\n\t\tthis.namespace = namespace;\n\t}\n\n\tpublic String getEndpoint() {\n\t\treturn endpoint;\n\t}\n\n\tpublic void setEndpoint(String endpoint) {\n\t\tthis.endpoint = endpoint;\n\t}\n\n\tpublic String getEndpointPort() {\n\t\treturn endpointPort;\n\t}\n\n\tpublic void setEndpointPort(String endpointPort) {\n\t\tthis.endpointPort = endpointPort;\n\t}\n\n\tpublic String getNamespaceName() {\n\t\treturn namespaceName;\n\t}\n\n\tpublic void setNamespaceName(String namespaceName) {\n\t\tthis.namespaceName = namespaceName;\n\t}\n\n\tpublic String getNamespaceSource() {\n\t\treturn namespaceSource;\n\t}\n\n\tpublic void setNamespaceSource(String namespaceSource) {\n\t\tthis.namespaceSource = namespaceSource;\n\t}\n\n\tpublic int getMaxTaskBodySize() {\n\t\treturn maxTaskBodySize;\n\t}\n\n\tpublic void setMaxTaskBodySize(int maxTaskBodySize) {\n\t\tthis.maxTaskBodySize = maxTaskBodySize;\n\t}\n\n\tpublic boolean isBlockAppStart() {\n\t\treturn blockAppStart;\n\t}\n\n\tpublic void setBlockAppStart(boolean blockAppStart) {\n\t\tthis.blockAppStart = blockAppStart;\n\t}\n\n\tpublic String getAppName() {\n\t\treturn appName;\n\t}\n\n\tpublic void setAppName(String appName) {\n\t\tthis.appName = appName;\n\t}\n\n\tpublic String getAppKey() {\n\t\treturn appKey;\n\t}\n\n\tpublic void setAppKey(String appKey) {\n\t\tthis.appKey = appKey;\n\t}\n\n\tpublic String getStsAccessKey() {\n\t\treturn stsAccessKey;\n\t}\n\n\tpublic void setStsAccessKey(String stsAccessKey) {\n\t\tthis.stsAccessKey = stsAccessKey;\n\t}\n\n\tpublic String getStsSecretKey() {\n\t\treturn stsSecretKey;\n\t}\n\n\tpublic void setStsSecretKey(String stsSecretKey) {\n\t\tthis.stsSecretKey = stsSecretKey;\n\t}\n\n\tpublic String getStsToken() {\n\t\treturn stsToken;\n\t}\n\n\tpublic String getAliyunRamRole() {\n\t\treturn aliyunRamRole;\n\t}\n\n\tpublic void setAliyunRamRole(String aliyunRamRole) {\n\t\tthis.aliyunRamRole = aliyunRamRole;\n\t}\n\n\tpublic void setStsToken(String stsToken) {\n\t\tthis.stsToken = stsToken;\n\t}\n\n\tpublic boolean isSlsCollectorEnable() {\n\t\treturn slsCollectorEnable;\n\t}\n\n\tpublic void setSlsCollectorEnable(boolean slsCollectorEnable) {\n\t\tthis.slsCollectorEnable = slsCollectorEnable;\n\t}\n\n\tpublic boolean isShareContainerPool() {\n\t\treturn shareContainerPool;\n\t}\n\n\tpublic void setShareContainerPool(boolean shareContainerPool) {\n\t\tthis.shareContainerPool = shareContainerPool;\n\t}\n\n\tpublic int getSharePoolSize() {\n\t\treturn sharePoolSize;\n\t}\n\n\tpublic void setSharePoolSize(int sharePoolSize) {\n\t\tthis.sharePoolSize = sharePoolSize;\n\t}\n\n\tpublic String getLabel() {\n\t\treturn label;\n\t}\n\n\tpublic void setLabel(String label) {\n\t\tif (label != null) {\n\t\t\tif (label.startsWith(\"#\") && label.endsWith(\"#\")) {\n\t\t\t\tString labelKey = label.substring(1, label.length() - 1);\n\t\t\t\tthis.label = System.getenv(labelKey);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tthis.label = label;\n\t}\n\n\tpublic String getLabelPath() {\n\t\treturn labelPath;\n\t}\n\n\tpublic void setLabelPath(String labelPath) {\n\t\tthis.labelPath = labelPath;\n\t}\n\n\tpublic boolean isEnableCgroupMetrics() {\n\t\treturn enableCgroupMetrics;\n\t}\n\n\tpublic void setEnableCgroupMetrics(boolean enableCgroupMetrics) {\n\t\tthis.enableCgroupMetrics = enableCgroupMetrics;\n\t}\n\n\tpublic String getCgroupPathPrefix() {\n\t\treturn cgroupPathPrefix;\n\t}\n\n\tpublic void setCgroupPathPrefix(String cgroupPathPrefix) {\n\t\tthis.cgroupPathPrefix = cgroupPathPrefix;\n\t}\n\n\tpublic boolean isAkkaRemotingAutoRecover() {\n\t\treturn akkaRemotingAutoRecover;\n\t}\n\n\tpublic void setAkkaRemotingAutoRecover(boolean akkaRemotingAutoRecover) {\n\t\tthis.akkaRemotingAutoRecover = akkaRemotingAutoRecover;\n\t}\n\n\tpublic boolean isEnableHeartbeatLog() {\n\t\treturn enableHeartbeatLog;\n\t}\n\n\tpublic void setEnableHeartbeatLog(boolean enableHeartbeatLog) {\n\t\tthis.enableHeartbeatLog = enableHeartbeatLog;\n\t}\n\n\tpublic int getMapMasterStatusCheckInterval() {\n\t\treturn mapMasterStatusCheckInterval;\n\t}\n\n\tpublic void setMapMasterStatusCheckInterval(int mapMasterStatusCheckInterval) {\n\t\tthis.mapMasterStatusCheckInterval = mapMasterStatusCheckInterval;\n\t}\n\n\tpublic boolean isEnableSecondDelayCycleIntervalMs() {\n\t\treturn enableSecondDelayCycleIntervalMs;\n\t}\n\n\tpublic void setEnableSecondDelayCycleIntervalMs(boolean enableSecondDelayCycleIntervalMs) {\n\t\tthis.enableSecondDelayCycleIntervalMs = enableSecondDelayCycleIntervalMs;\n\t}\n\n\tpublic boolean isEnableMapMasterFailover() {\n\t\treturn enableMapMasterFailover;\n\t}\n\n\tpublic void setEnableMapMasterFailover(boolean enableMapMasterFailover) {\n\t\tthis.enableMapMasterFailover = enableMapMasterFailover;\n\t}\n\n\tpublic boolean isEnableSecondDelayStandaloneDispatch() {\n\t\treturn enableSecondDelayStandaloneDispatch;\n\t}\n\n\tpublic void setEnableSecondDelayStandaloneDispatch(boolean enableSecondDelayStandaloneDispatch) {\n\t\tthis.enableSecondDelayStandaloneDispatch = enableSecondDelayStandaloneDispatch;\n\t}\n\n\tpublic int getPageSize() {\n\t\treturn pageSize;\n\t}\n\n\tpublic String getGraceShutdownMode() {\n\t\treturn graceShutdownMode;\n\t}\n\n\tpublic void setGraceShutdownMode(String graceShutdownMode) {\n\t\tthis.graceShutdownMode = graceShutdownMode;\n\t}\n\n\tpublic long getGraceShutdownTimeout() {\n\t\treturn graceShutdownTimeout;\n\t}\n\n\tpublic void setGraceShutdownTimeout(long graceShutdownTimeout) {\n\t\tthis.graceShutdownTimeout = graceShutdownTimeout;\n\t}\n\n\tpublic void setPageSize(int pageSize) {\n\t\tthis.pageSize = pageSize;\n\t}\n\n\tpublic String getRegionId() {\n\t\treturn regionId;\n\t}\n\n\tpublic void setRegionId(String regionId) {\n\t\tthis.regionId = regionId;\n\t}\n\n\tpublic Map<String, JobProperty> getJobs() {\n\t\treturn jobs;\n\t}\n\n\tpublic void setJobs(Map<String, JobProperty> jobs) {\n\t\tthis.jobs = jobs;\n\t}\n\n\tpublic String getAlarmChannel() {\n\t\treturn alarmChannel;\n\t}\n\n\tpublic void setAlarmChannel(String alarmChannel) {\n\t\tthis.alarmChannel = alarmChannel;\n\t}\n\n\tpublic Map<String, ContactInfo> getAlarmUsers() {\n\t\treturn alarmUsers;\n\t}\n\n\tpublic void setAlarmUsers(Map<String, ContactInfo> alarmUsers) {\n\t\tthis.alarmUsers = alarmUsers;\n\t}\n\n\tpublic int getBroadcastDispatchThreadNum() {\n\t\treturn broadcastDispatchThreadNum;\n\t}\n\n\tpublic void setBroadcastDispatchThreadNum(int broadcastDispatchThreadNum) {\n\t\tthis.broadcastDispatchThreadNum = broadcastDispatchThreadNum;\n\t}\n\n\tpublic boolean isBroadcastDispatchThreadEnable() {\n\t\treturn broadcastDispatchThreadEnable;\n\t}\n\n\tpublic void setBroadcastDispatchThreadEnable(boolean broadcastDispatchThreadEnable) {\n\t\tthis.broadcastDispatchThreadEnable = broadcastDispatchThreadEnable;\n\t}\n\n\tpublic String getThreadPoolMode() {\n\t\treturn threadPoolMode;\n\t}\n\n\tpublic void setThreadPoolMode(String threadPoolMode) {\n\t\tthis.threadPoolMode = threadPoolMode;\n\t}\n\n\tpublic Map<String, Integer> getProcessorPoolSize() {\n\t\treturn processorPoolSize;\n\t}\n\n\tpublic void setProcessorPoolSize(Map<String, Integer> processorPoolSize) {\n\t\tthis.processorPoolSize = processorPoolSize;\n\t}\n\n\tpublic int getSharePoolQueueSize() {\n\t\treturn sharePoolQueueSize;\n\t}\n\n\tpublic void setSharePoolQueueSize(int sharePoolQueueSize) {\n\t\tthis.sharePoolQueueSize = sharePoolQueueSize;\n\t}\n\n\tpublic boolean isMapMasterDispatchRandom() {\n\t\treturn mapMasterDispatchRandom;\n\t}\n\n\tpublic void setMapMasterDispatchRandom(boolean mapMasterDispatchRandom) {\n\t\tthis.mapMasterDispatchRandom = mapMasterDispatchRandom;\n\t}\n\n\tpublic boolean isBroadcastMasterExecEnable() {\n\t\treturn broadcastMasterExecEnable;\n\t}\n\n\tpublic void setBroadcastMasterExecEnable(boolean broadcastMasterExecEnable) {\n\t\tthis.broadcastMasterExecEnable = broadcastMasterExecEnable;\n\t}\n\n\tpublic int getBroadcastDispatchRetryTimes() {\n\t\treturn broadcastDispatchRetryTimes;\n\t}\n\n\tpublic void setBroadcastDispatchRetryTimes(int broadcastDispatchRetryTimes) {\n\t\tthis.broadcastDispatchRetryTimes = broadcastDispatchRetryTimes;\n\t}\n\n\tpublic Integer getMapMasterRouterStrategy() {\n\t\treturn mapMasterRouterStrategy;\n\t}\n\n\tpublic void setMapMasterRouterStrategy(Integer mapMasterRouterStrategy) {\n\t\tthis.mapMasterRouterStrategy = mapMasterRouterStrategy;\n\t}\n\n\tpublic String getH2DatabaseUser() {\n\t\treturn h2DatabaseUser;\n\t}\n\n\tpublic void setH2DatabaseUser(String h2DatabaseUser) {\n\t\tthis.h2DatabaseUser = h2DatabaseUser;\n\t}\n\n\tpublic String getH2DatabasePassword() {\n\t\treturn h2DatabasePassword;\n\t}\n\n\tpublic void setH2DatabasePassword(String h2DatabasePassword) {\n\t\tthis.h2DatabasePassword = h2DatabasePassword;\n\t}\n\n\tpublic Boolean getHttpServerEnable() {\n\t\treturn httpServerEnable;\n\t}\n\n\tpublic void setHttpServerEnable(Boolean httpServerEnable) {\n\t\tthis.httpServerEnable = httpServerEnable;\n\t}\n\n\tpublic Integer getHttpServerPort() {\n\t\treturn httpServerPort;\n\t}\n\n\tpublic void setHttpServerPort(Integer httpServerPort) {\n\t\tthis.httpServerPort = httpServerPort;\n\t}\n\n\tpublic Float getMaxMapDiskPercent() {\n\t\treturn maxMapDiskPercent;\n\t}\n\n\tpublic void setMaxMapDiskPercent(float maxMapDiskPercent) {\n\t\tthis.maxMapDiskPercent = maxMapDiskPercent;\n\t}\n\n\t@Override\n\tpublic void afterPropertiesSet() {\n\t\tlogger.info(\"SchedulerxProperties->\" + JsonUtil.toJson(this));\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/java/com/alibaba/cloud/scheduling/schedulerx/constants/SchedulerxConstants.java",
    "content": "/*\n * Copyright 2024-present the original author or 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\npackage com.alibaba.cloud.scheduling.schedulerx.constants;\n\n/**\n * Schedulerx constants.\n *\n * @author yaohui\n */\npublic final class SchedulerxConstants {\n\n\t/**\n\t * Schedulerx default namespace source.\n\t */\n\tpublic static final String NAMESPACE_SOURCE_SPRINGBOOT = \"springboot\";\n\n\t/**\n\t * Aliyun pop product.\n\t */\n\tpublic static final String ALIYUN_POP_PRODUCT = \"schedulerx2\";\n\n\t/**\n\t * Aliyun pop endpoint.\n\t */\n\tpublic static final String ALIYUN_POP_SCHEDULERX_ENDPOINT = \"schedulerx.aliyuncs.com\";\n\n\t/**\n\t * Second delay max value.\n\t */\n\tpublic static final int SECOND_DELAY_MAX_VALUE = 60;\n\n\t/**\n\t * Second delay min value.\n\t */\n\tpublic static final int SECOND_DELAY_MIN_VALUE = 1;\n\n\t/**\n\t * Job timeout default value.\n\t */\n\tpublic static final long JOB_TIMEOUT_DEFAULT = 3600L;\n\n\t/**\n\t * Job retry count default value.\n\t */\n\tpublic static final int JOB_RETRY_COUNT_DEFAULT = 3;\n\n\t/**\n\t * Job retry interval default value.\n\t */\n\tpublic static final int JOB_RETRY_INTERVAL_DEFAULT = 30;\n\n\t/**\n\t * Job alarm channel default value.\n\t */\n\tpublic static final String JOB_ALARM_CHANNEL_DEFAULT = \"default\";\n\n\t/**\n\t * Job model mapreduce alias.\n\t */\n\tpublic static final String JOB_MODEL_MAPREDUCE_ALIAS = \"mapreduce\";\n\n\t@Override\n\tpublic String toString() {\n\t\treturn super.toString();\n\t}\n\n\tprivate SchedulerxConstants() {\n\t\tthrow new AssertionError(\"Must not instantiate constant utility class\");\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/java/com/alibaba/cloud/scheduling/schedulerx/service/JobSyncService.java",
    "content": "/*\n * Copyright 2024-present the original author or 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\npackage com.alibaba.cloud.scheduling.schedulerx.service;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.concurrent.TimeUnit;\n\nimport com.alibaba.cloud.scheduling.schedulerx.JobProperty;\nimport com.alibaba.cloud.scheduling.schedulerx.SchedulerxProperties;\nimport com.alibaba.cloud.scheduling.schedulerx.constants.SchedulerxConstants;\nimport com.alibaba.cloud.scheduling.schedulerx.util.CronExpression;\nimport com.alibaba.schedulerx.common.domain.ContactInfo;\nimport com.alibaba.schedulerx.common.domain.ExecuteMode;\nimport com.alibaba.schedulerx.common.domain.JobType;\nimport com.alibaba.schedulerx.common.domain.TimeType;\nimport com.alibaba.schedulerx.common.sdk.common.MonitorConfig;\nimport com.alibaba.schedulerx.common.util.JsonUtil;\nimport com.alibaba.schedulerx.common.util.StringUtils;\nimport com.alibaba.schedulerx.worker.log.LogFactory;\nimport com.alibaba.schedulerx.worker.log.Logger;\nimport com.aliyuncs.DefaultAcsClient;\nimport com.aliyuncs.auth.InstanceProfileCredentialsProvider;\nimport com.aliyuncs.exceptions.ClientException;\nimport com.aliyuncs.profile.DefaultProfile;\nimport com.aliyuncs.schedulerx2.model.v20190430.CreateAppGroupRequest;\nimport com.aliyuncs.schedulerx2.model.v20190430.CreateAppGroupResponse;\nimport com.aliyuncs.schedulerx2.model.v20190430.CreateJobRequest;\nimport com.aliyuncs.schedulerx2.model.v20190430.CreateJobResponse;\nimport com.aliyuncs.schedulerx2.model.v20190430.CreateNamespaceRequest;\nimport com.aliyuncs.schedulerx2.model.v20190430.CreateNamespaceResponse;\nimport com.aliyuncs.schedulerx2.model.v20190430.GetJobInfoRequest;\nimport com.aliyuncs.schedulerx2.model.v20190430.GetJobInfoResponse;\nimport com.aliyuncs.schedulerx2.model.v20190430.GetJobInfoResponse.Data.JobConfigInfo;\nimport com.aliyuncs.schedulerx2.model.v20190430.UpdateJobRequest;\nimport com.aliyuncs.schedulerx2.model.v20190430.UpdateJobResponse;\n\nimport org.springframework.beans.factory.annotation.Autowired;\n\n\n/**\n * JobSyncService.\n *\n * @author xiaomeng.hxm\n */\npublic class JobSyncService {\n\n\tprivate static final Logger logger = LogFactory.getLogger(JobSyncService.class);\n\n\t@Autowired\n\tprivate SchedulerxProperties properties;\n\n\tprivate DefaultAcsClient client;\n\n\tprivate synchronized DefaultAcsClient getClient() {\n\t\t// build aliyun pop client\n\t\tif (client == null) {\n\t\t\tDefaultProfile.addEndpoint(properties.getRegionId(), SchedulerxConstants.ALIYUN_POP_PRODUCT, SchedulerxConstants.ALIYUN_POP_SCHEDULERX_ENDPOINT);\n\t\t\tif (StringUtils.isNotEmpty(properties.getAliyunRamRole())) {\n\t\t\t\tDefaultProfile profile = DefaultProfile.getProfile(properties.getRegionId());\n\t\t\t\tInstanceProfileCredentialsProvider provider = new InstanceProfileCredentialsProvider(\n\t\t\t\t\t\tproperties.getAliyunRamRole());\n\t\t\t\tclient = new DefaultAcsClient(profile, provider);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tDefaultProfile defaultProfile = DefaultProfile.getProfile(properties.getRegionId(),\n\t\t\t\t\t\tproperties.getAliyunAccessKey(),\n\t\t\t\t\t\tproperties.getAliyunSecretKey());\n\t\t\t\tclient = new DefaultAcsClient(defaultProfile);\n\t\t\t}\n\t\t}\n\t\treturn client;\n\t}\n\n\t/**\n\t * Sync job config.\n\t *\n\t * @param jobs            job configs\n\t * @param namespaceSource namespace source\n\t * @throws Exception sync job config exception\n\t */\n\tpublic synchronized void syncJobs(Map<String, JobProperty> jobs, String namespaceSource) throws Exception {\n\t\tDefaultAcsClient client = getClient();\n\t\tfor (Entry<String, JobProperty> entry : jobs.entrySet()) {\n\t\t\tString jobName = entry.getKey();\n\t\t\tJobProperty jobProperty = entry.getValue();\n\t\t\tJobConfigInfo jobConfigInfo = getJob(client, jobName, namespaceSource);\n\t\t\tif (jobConfigInfo == null) {\n\t\t\t\tcreateJob(client, jobName, jobProperty, namespaceSource);\n\t\t\t}\n\t\t\telse if (jobProperty.isOverwrite()) {\n\t\t\t\tupdateJob(client, jobConfigInfo, jobProperty, namespaceSource);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * sync jobs.\n\t *\n\t * @throws Exception sync jobs exception\n\t */\n\tpublic void syncJobs() throws Exception {\n\t\t// 1. create namespace\n\t\tif (syncNamespace(getClient())) {\n\t\t\t// 2. create app group\n\t\t\tif (syncAppGroup(getClient())) {\n\t\t\t\tsyncJobs(properties.getJobs(), getNamespaceSource());\n\t\t\t\tproperties.setNamespaceSource(getNamespaceSource());\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * sync namespace.\n\t *\n\t * @param client pop client\n\t * @return true if success\n\t * @throws Exception sync namespace exception\n\t */\n\tpublic boolean syncNamespace(DefaultAcsClient client) throws Exception {\n\t\tif (StringUtils.isEmpty(properties.getNamespace())) {\n\t\t\tlogger.error(\"please set {}.namespace\", SchedulerxProperties.CONFIG_PREFIX);\n\t\t\tthrow new IOException(String.format(\"please set %s.namespace\", SchedulerxProperties.CONFIG_PREFIX));\n\t\t}\n\n\t\tif (StringUtils.isEmpty(properties.getNamespaceName())) {\n\t\t\tlogger.error(\"please set {}.namespaceName\", SchedulerxProperties.CONFIG_PREFIX);\n\t\t\tthrow new IOException(String.format(\"please set %s.namespaceName\", SchedulerxProperties.CONFIG_PREFIX));\n\t\t}\n\n\t\tCreateNamespaceRequest request = new CreateNamespaceRequest();\n\t\trequest.setUid(properties.getNamespace());\n\t\trequest.setName(properties.getNamespaceName());\n\t\trequest.setSource(getNamespaceSource());\n\t\tCreateNamespaceResponse response = client.getAcsResponse(request);\n\t\tif (response.getSuccess()) {\n\t\t\tlogger.info(JsonUtil.toJson(response));\n\t\t\treturn true;\n\t\t}\n\t\telse {\n\t\t\tthrow new IOException(response.getMessage());\n\t\t}\n\n\t}\n\n\t/**\n\t * sync app group.\n\t *\n\t * @param client pop client\n\t * @return sync app group result\n\t * @throws IOException     sync app group exception.\n\t * @throws ClientException sync app group pop client exception.\n\t */\n\tpublic boolean syncAppGroup(DefaultAcsClient client) throws IOException, ClientException {\n\t\tif (StringUtils.isEmpty(properties.getAppName())) {\n\t\t\tlogger.error(\"please set {}.appName\", SchedulerxProperties.CONFIG_PREFIX);\n\t\t\tthrow new IOException(String.format(\"please set %s.appName\", SchedulerxProperties.CONFIG_PREFIX));\n\t\t}\n\n\t\tif (StringUtils.isEmpty(properties.getAppKey())) {\n\t\t\tlogger.error(\"please set {}.appKey\", SchedulerxProperties.CONFIG_PREFIX);\n\t\t\tthrow new IOException(String.format(\"please set %s.appKey\", SchedulerxProperties.CONFIG_PREFIX));\n\t\t}\n\n\t\tif (StringUtils.isEmpty(properties.getGroupId())) {\n\t\t\tlogger.error(\"please set {}.groupId\", SchedulerxProperties.CONFIG_PREFIX);\n\t\t\tthrow new IOException(String.format(\"please set %s.groupId\", SchedulerxProperties.CONFIG_PREFIX));\n\t\t}\n\n\t\tCreateAppGroupRequest request = new CreateAppGroupRequest();\n\t\trequest.setNamespace(properties.getNamespace());\n\t\trequest.setNamespaceSource(getNamespaceSource());\n\t\trequest.setAppName(properties.getAppName());\n\t\trequest.setGroupId(properties.getGroupId());\n\t\trequest.setAppKey(properties.getAppKey());\n\t\tif (StringUtils.isNotEmpty(properties.getAlarmChannel())) {\n\t\t\tMonitorConfig monitorConfig = new MonitorConfig();\n\t\t\tmonitorConfig.setSendChannel(properties.getAlarmChannel());\n\t\t\trequest.setMonitorConfigJson(JsonUtil.toJson(monitorConfig));\n\t\t}\n\t\tif (!properties.getAlarmUsers().isEmpty()) {\n\t\t\tList<ContactInfo> contactInfos = new ArrayList(properties.getAlarmUsers().values());\n\t\t\trequest.setMonitorContactsJson(JsonUtil.toJson(contactInfos));\n\t\t}\n\t\tCreateAppGroupResponse response = client.getAcsResponse(request);\n\t\tif (response.getSuccess()) {\n\t\t\tlogger.info(JsonUtil.toJson(response));\n\t\t\treturn true;\n\t\t}\n\t\telse {\n\t\t\tthrow new IOException(response.getMessage());\n\t\t}\n\t}\n\n\t/**\n\t * Get job config info.\n\t *\n\t * @param client          pop client\n\t * @param jobName         job name\n\t * @param namespaceSource namespace source\n\t * @return job config info.\n\t * @throws Exception get job config info exception.\n\t */\n\tprivate JobConfigInfo getJob(DefaultAcsClient client, String jobName, String namespaceSource) throws Exception {\n\t\tGetJobInfoRequest request = new GetJobInfoRequest();\n\t\trequest.setNamespace(properties.getNamespace());\n\t\trequest.setNamespaceSource(namespaceSource);\n\t\trequest.setGroupId(properties.getGroupId());\n\t\trequest.setJobId(0L);\n\t\trequest.setJobName(jobName);\n\t\tGetJobInfoResponse response = client.getAcsResponse(request);\n\t\tif (response.getSuccess()) {\n\t\t\treturn response.getData().getJobConfigInfo();\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * create job.\n\t *\n\t * @param client          pop client\n\t * @param jobName         job name\n\t * @param jobProperty     job property\n\t * @param namespaceSource namespace source\n\t * @throws Exception create job exception\n\t */\n\tprivate void createJob(DefaultAcsClient client, String jobName, JobProperty jobProperty, String namespaceSource) throws Exception {\n\t\tCreateJobRequest request = new CreateJobRequest();\n\t\trequest.setNamespace(properties.getNamespace());\n\t\trequest.setNamespaceSource(namespaceSource);\n\t\trequest.setGroupId(properties.getGroupId());\n\t\trequest.setName(jobName);\n\t\trequest.setParameters(jobProperty.getJobParameter());\n\n\t\tif (jobProperty.getJobType().equals(JobType.JAVA.getKey())) {\n\t\t\trequest.setJobType(JobType.JAVA.getKey());\n\t\t\trequest.setClassName(jobProperty.getClassName());\n\t\t}\n\t\telse {\n\t\t\trequest.setJobType(jobProperty.getJobType());\n\t\t}\n\n\t\tif (SchedulerxConstants.JOB_MODEL_MAPREDUCE_ALIAS.equals(jobProperty.getJobModel())) {\n\t\t\trequest.setExecuteMode(ExecuteMode.BATCH.getKey());\n\t\t}\n\t\telse {\n\t\t\trequest.setExecuteMode(jobProperty.getJobModel());\n\t\t}\n\t\tif (StringUtils.isNotEmpty(jobProperty.getDescription())) {\n\t\t\trequest.setDescription(jobProperty.getDescription());\n\t\t}\n\n\t\tif (StringUtils.isNotEmpty(jobProperty.getContent())) {\n\t\t\trequest.setContent(jobProperty.getContent());\n\t\t}\n\n\t\tif (StringUtils.isNotEmpty(jobProperty.getCron()) && StringUtils.isNotEmpty(jobProperty.getOneTime())) {\n\t\t\tthrow new IOException(\"cron and oneTime shouldn't set together\");\n\t\t}\n\t\tif (StringUtils.isNotEmpty(jobProperty.getCron())) {\n\t\t\tCronExpression cronExpression = new CronExpression(jobProperty.getCron());\n\t\t\tDate now = new Date();\n\t\t\tDate nextData = cronExpression.getTimeAfter(now);\n\t\t\tDate next2Data = cronExpression.getTimeAfter(nextData);\n\t\t\tif (nextData != null && next2Data != null) {\n\t\t\t\tlong interval = TimeUnit.MILLISECONDS.toSeconds((next2Data.getTime() - nextData.getTime()));\n\t\t\t\tif (interval < SchedulerxConstants.SECOND_DELAY_MAX_VALUE) {\n\t\t\t\t\trequest.setTimeType(TimeType.SECOND_DELAY.getValue());\n\t\t\t\t\trequest.setTimeExpression(String.valueOf(interval < SchedulerxConstants.SECOND_DELAY_MIN_VALUE ?\n\t\t\t\t\t\t\tSchedulerxConstants.SECOND_DELAY_MIN_VALUE : interval));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\trequest.setTimeType(TimeType.CRON.getValue());\n\t\t\t\t\trequest.setTimeExpression(jobProperty.getCron());\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\trequest.setTimeType(TimeType.CRON.getValue());\n\t\t\t\trequest.setTimeExpression(jobProperty.getCron());\n\t\t\t}\n\t\t}\n\t\telse if (StringUtils.isNotEmpty(jobProperty.getOneTime())) {\n\t\t\trequest.setTimeType(TimeType.ONE_TIME.getValue());\n\t\t\trequest.setTimeExpression(jobProperty.getOneTime());\n\t\t}\n\t\telse {\n\t\t\trequest.setTimeType(TimeType.API.getValue());\n\t\t}\n\n\t\tif (jobProperty.getTimeType() != null) {\n\t\t\trequest.setTimeType(jobProperty.getTimeType());\n\t\t\tif (StringUtils.isNotEmpty(jobProperty.getTimeExpression())) {\n\t\t\t\trequest.setTimeExpression(jobProperty.getTimeExpression());\n\t\t\t}\n\t\t}\n\n\t\trequest.setTimeoutEnable(true);\n\t\trequest.setTimeoutKillEnable(true);\n\t\trequest.setSendChannel(SchedulerxConstants.JOB_ALARM_CHANNEL_DEFAULT);\n\t\trequest.setFailEnable(true);\n\t\trequest.setTimeout(SchedulerxConstants.JOB_TIMEOUT_DEFAULT);\n\t\trequest.setMaxAttempt(SchedulerxConstants.JOB_RETRY_COUNT_DEFAULT);\n\t\trequest.setAttemptInterval(SchedulerxConstants.JOB_RETRY_INTERVAL_DEFAULT);\n\t\tCreateJobResponse response = client.getAcsResponse(request);\n\t\tif (response.getSuccess()) {\n\t\t\tlogger.info(\"create schedulerx job successfully, jobId={}, jobName={}\", response.getData().getJobId(), jobName);\n\t\t}\n\t\telse {\n\t\t\tthrow new IOException(\"create schedulerx job failed, jobName=\" + jobName + \", message=\" + response.getMessage());\n\t\t}\n\t}\n\n\t/**\n\t * update job.\n\t *\n\t * @param client          pop client\n\t * @param jobConfigInfo   job config info\n\t * @param jobProperty     job property\n\t * @param namespaceSource namespace source\n\t * @throws Exception update job exception\n\t */\n\tprivate void updateJob(DefaultAcsClient client, JobConfigInfo jobConfigInfo, JobProperty jobProperty, String namespaceSource) throws Exception {\n\t\tString executeMode = jobProperty.getJobModel();\n\t\tif (SchedulerxConstants.JOB_MODEL_MAPREDUCE_ALIAS.equals(jobProperty.getJobModel())) {\n\t\t\texecuteMode = ExecuteMode.BATCH.getKey();\n\t\t}\n\t\tint timeType;\n\t\tString timeExpression = null;\n\t\tif (StringUtils.isNotEmpty(jobProperty.getCron()) && StringUtils.isNotEmpty(jobProperty.getOneTime())) {\n\t\t\tthrow new IOException(\"cron and oneTime shouldn't set together\");\n\t\t}\n\t\tif (StringUtils.isNotEmpty(jobProperty.getCron())) {\n\t\t\tCronExpression cronExpression = new CronExpression(jobProperty.getCron());\n\t\t\tDate now = new Date();\n\t\t\tDate nextData = cronExpression.getTimeAfter(now);\n\t\t\tDate next2Data = cronExpression.getTimeAfter(nextData);\n\t\t\tif (nextData != null && next2Data != null) {\n\t\t\t\tlong interval = TimeUnit.MILLISECONDS.toSeconds((next2Data.getTime() - nextData.getTime()));\n\t\t\t\tif (interval < SchedulerxConstants.SECOND_DELAY_MAX_VALUE) {\n\t\t\t\t\ttimeType = TimeType.SECOND_DELAY.getValue();\n\t\t\t\t\ttimeExpression = String.valueOf(interval < SchedulerxConstants.SECOND_DELAY_MIN_VALUE ?\n\t\t\t\t\t\t\tSchedulerxConstants.SECOND_DELAY_MIN_VALUE : interval);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttimeType = TimeType.CRON.getValue();\n\t\t\t\t\ttimeExpression = jobProperty.getCron();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\ttimeType = TimeType.CRON.getValue();\n\t\t\t\ttimeExpression = jobProperty.getCron();\n\t\t\t}\n\t\t}\n\t\telse if (StringUtils.isNotEmpty(jobProperty.getOneTime())) {\n\t\t\ttimeType = TimeType.ONE_TIME.getValue();\n\t\t\ttimeExpression = jobProperty.getOneTime();\n\t\t}\n\t\telse {\n\t\t\ttimeType = TimeType.API.getValue();\n\t\t}\n\n\t\tif (!jobConfigInfo.getDescription().equals(jobProperty.getDescription())\n\t\t\t\t|| !jobConfigInfo.getClassName().equals(jobProperty.getClassName())\n\t\t\t\t|| !jobConfigInfo.getParameters().equals(jobProperty.getJobParameter())\n\t\t\t\t|| !jobConfigInfo.getExecuteMode().equals(executeMode)\n\t\t\t\t|| jobConfigInfo.getTimeConfig().getTimeType() != timeType\n\t\t\t\t|| !jobConfigInfo.getTimeConfig().getTimeExpression().equals(timeExpression)) {\n\n\t\t\tUpdateJobRequest request = new UpdateJobRequest();\n\t\t\trequest.setNamespace(properties.getNamespace());\n\t\t\trequest.setNamespaceSource(namespaceSource);\n\t\t\trequest.setGroupId(properties.getGroupId());\n\t\t\trequest.setJobId(jobConfigInfo.getJobId());\n\t\t\trequest.setName(jobConfigInfo.getName());\n\t\t\trequest.setParameters(jobProperty.getJobParameter());\n\n\t\t\t//java任务\n\t\t\tif (jobProperty.getJobType().equals(JobType.JAVA.getKey())) {\n\t\t\t\trequest.setClassName(jobProperty.getClassName());\n\t\t\t}\n\t\t\trequest.setExecuteMode(executeMode);\n\t\t\tif (StringUtils.isNotEmpty(jobProperty.getDescription())) {\n\t\t\t\trequest.setDescription(jobProperty.getDescription());\n\t\t\t}\n\t\t\trequest.setTimeType(timeType);\n\t\t\trequest.setTimeExpression(timeExpression);\n\n\t\t\trequest.setTimeoutEnable(true);\n\t\t\trequest.setTimeoutKillEnable(true);\n\t\t\trequest.setSendChannel(SchedulerxConstants.JOB_ALARM_CHANNEL_DEFAULT);\n\t\t\trequest.setFailEnable(true);\n\t\t\trequest.setTimeout(SchedulerxConstants.JOB_TIMEOUT_DEFAULT);\n\t\t\trequest.setMaxAttempt(SchedulerxConstants.JOB_RETRY_COUNT_DEFAULT);\n\t\t\trequest.setAttemptInterval(SchedulerxConstants.JOB_RETRY_INTERVAL_DEFAULT);\n\n\t\t\tUpdateJobResponse response = client.getAcsResponse(request);\n\t\t\tif (response.getSuccess()) {\n\t\t\t\tlogger.info(\"update schedulerx job successfully, jobId={}, jobName={}\", jobConfigInfo.getJobId(), jobConfigInfo.getName());\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new IOException(\"update schedulerx job failed, jobName=\" + jobConfigInfo.getName() + \", message=\" + response.getMessage());\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get namespace source.\n\t *\n\t * @return namespace source\n\t */\n\tprivate String getNamespaceSource() {\n\t\tif (StringUtils.isEmpty(properties.getNamespaceSource())) {\n\t\t\treturn SchedulerxConstants.NAMESPACE_SOURCE_SPRINGBOOT;\n\t\t}\n\t\treturn properties.getNamespaceSource();\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/java/com/alibaba/cloud/scheduling/schedulerx/service/ScheduledJobSyncConfigurer.java",
    "content": "/*\n * Copyright 2024-present the original author or 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\npackage com.alibaba.cloud.scheduling.schedulerx.service;\n\nimport java.lang.reflect.Method;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport com.alibaba.cloud.scheduling.schedulerx.JobProperty;\nimport com.alibaba.cloud.scheduling.schedulerx.SchedulerxProperties;\nimport com.alibaba.schedulerx.common.domain.ExecuteMode;\nimport com.alibaba.schedulerx.common.domain.JobType;\nimport com.alibaba.schedulerx.common.domain.Pair;\nimport com.alibaba.schedulerx.common.domain.TimeType;\nimport com.alibaba.schedulerx.common.util.JsonUtil;\nimport com.alibaba.schedulerx.common.util.StringUtils;\nimport com.alibaba.schedulerx.scheduling.annotation.SchedulerX;\nimport com.alibaba.schedulerx.worker.domain.SpringScheduleProfile;\nimport com.alibaba.schedulerx.worker.log.LogFactory;\nimport com.alibaba.schedulerx.worker.log.Logger;\nimport com.alibaba.schedulerx.worker.processor.springscheduling.SchedulerxJobRegister;\n\nimport org.springframework.aop.framework.AopProxyUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.core.annotation.AnnotatedElementUtils;\nimport org.springframework.scheduling.annotation.SchedulingConfigurer;\nimport org.springframework.scheduling.config.CronTask;\nimport org.springframework.scheduling.config.IntervalTask;\nimport org.springframework.scheduling.config.ScheduledTaskRegistrar;\nimport org.springframework.scheduling.config.Task;\nimport org.springframework.scheduling.support.ScheduledMethodRunnable;\nimport org.springframework.util.ClassUtils;\nimport org.springframework.util.CollectionUtils;\n\n/**\n * Spring scheduled job sync.\n *\n * @author yaohui\n * @create 2022/8/17 下午2:21\n **/\npublic class ScheduledJobSyncConfigurer implements SchedulingConfigurer {\n\n\tprivate static final Logger logger = LogFactory.getLogger(ScheduledJobSyncConfigurer.class);\n\n\t@Autowired\n\tprivate JobSyncService jobSyncService;\n\n\t@Autowired\n\tprivate SchedulerxProperties properties;\n\n\t@Value(\"${\" + SchedulerxProperties.CONFIG_PREFIX + \".task-overwrite:false}\")\n\tprivate Boolean overwrite = false;\n\n\t@Value(\"${\" + SchedulerxProperties.CONFIG_PREFIX + \".task-model-default:broadcast}\")\n\tprivate String defaultModel = ExecuteMode.BROADCAST.getKey();\n\n\tprivate boolean isValidModel(String mode) {\n\t\tif (mode == null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn (ExecuteMode.BROADCAST.getKey().equals(mode) || ExecuteMode.STANDALONE.getKey().equals(mode));\n\t}\n\n\tprivate JobProperty convertToJobProperty(Task task, Object target, Method method) {\n\t\tJobProperty jobProperty = new JobProperty();\n\t\tClass targetClass = AopProxyUtils.ultimateTargetClass(target);\n\t\tif (ClassUtils.isCglibProxyClass(targetClass)) {\n\t\t\ttargetClass = ClassUtils.getUserClass(target);\n\t\t}\n\t\tString jobName = targetClass.getSimpleName() + \"_\" + method.getName();\n\t\tString model = this.defaultModel;\n\n\t\tif (task != null && task instanceof CronTask) {\n\t\t\tString expression = ((CronTask) task).getExpression();\n\t\t\tjobProperty.setCron(expression);\n\t\t}\n\n\t\tif (task != null && task instanceof IntervalTask) {\n\t\t\tlong interval = ((IntervalTask) task).getInterval() / 1000;\n\t\t\tinterval = interval < 1 ? 1 : interval;\n\t\t\tif (interval < 60) {\n\t\t\t\tjobProperty.setTimeType(TimeType.SECOND_DELAY.getValue());\n\t\t\t}\n\t\t\telse {\n\t\t\t\tjobProperty.setTimeType(TimeType.FIXED_RATE.getValue());\n\t\t\t}\n\t\t\tjobProperty.setTimeExpression(String.valueOf(interval));\n\t\t}\n\n\t\tSchedulerX schedulerXMethod = AnnotatedElementUtils.getMergedAnnotation(method, SchedulerX.class);\n\t\tif (schedulerXMethod != null) {\n\t\t\tif (StringUtils.isNotEmpty(schedulerXMethod.name())) {\n\t\t\t\tjobName = schedulerXMethod.name();\n\t\t\t}\n\t\t\tif (isValidModel(schedulerXMethod.model())) {\n\t\t\t\tmodel = schedulerXMethod.model();\n\t\t\t}\n\t\t\tif (StringUtils.isNotEmpty(schedulerXMethod.cron())) {\n\t\t\t\tjobProperty.setCron(schedulerXMethod.cron());\n\t\t\t}\n\t\t\tif (schedulerXMethod.fixedRate() > 0) {\n\t\t\t\tlong interval = schedulerXMethod.timeUnit().toSeconds(schedulerXMethod.fixedRate());\n\t\t\t\tinterval = interval < 1 ? 1 : interval;\n\t\t\t\tif (interval < 60) {\n\t\t\t\t\tjobProperty.setTimeType(TimeType.SECOND_DELAY.getValue());\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tjobProperty.setTimeType(TimeType.FIXED_RATE.getValue());\n\t\t\t\t}\n\t\t\t\tjobProperty.setTimeExpression(String.valueOf(interval));\n\t\t\t}\n\t\t}\n\n\t\tjobProperty.setJobName(jobName);\n\t\tjobProperty.setJobType(JobType.SPRINGSCHEDULE.getKey());\n\t\tjobProperty.setJobModel(model);\n\t\tSpringScheduleProfile profile = new SpringScheduleProfile();\n\t\tprofile.setClassName(targetClass.getName());\n\t\tprofile.setMethod(method.getName());\n\t\tjobProperty.setContent(JsonUtil.toJson(profile));\n\t\tjobProperty.setOverwrite(overwrite);\n\t\treturn jobProperty;\n\t}\n\n\t@Override\n\tpublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {\n\t\tlogger.info(\"spring scheduled job is not empty, start to sync jobs...\");\n\t\ttry {\n\t\t\tMap<String, JobProperty> jobs = new HashMap<>();\n\t\t\tif (!CollectionUtils.isEmpty(taskRegistrar.getCronTaskList())) {\n\t\t\t\tfor (CronTask cronTask : taskRegistrar.getCronTaskList()) {\n\t\t\t\t\tif (cronTask.getRunnable() instanceof ScheduledMethodRunnable) {\n\t\t\t\t\t\tScheduledMethodRunnable runnable = (ScheduledMethodRunnable) cronTask.getRunnable();\n\t\t\t\t\t\tJobProperty jobProperty = convertToJobProperty(cronTask, runnable.getTarget(), runnable.getMethod());\n\t\t\t\t\t\tjobs.put(jobProperty.getJobName(), jobProperty);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!CollectionUtils.isEmpty(taskRegistrar.getFixedDelayTaskList())) {\n\t\t\t\tfor (IntervalTask intervalTask : taskRegistrar.getFixedDelayTaskList()) {\n\t\t\t\t\tif (intervalTask.getRunnable() instanceof ScheduledMethodRunnable) {\n\t\t\t\t\t\tScheduledMethodRunnable runnable = (ScheduledMethodRunnable) intervalTask.getRunnable();\n\t\t\t\t\t\tJobProperty jobProperty = convertToJobProperty(intervalTask, runnable.getTarget(), runnable.getMethod());\n\t\t\t\t\t\tjobs.put(jobProperty.getJobName(), jobProperty);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!CollectionUtils.isEmpty(taskRegistrar.getFixedRateTaskList())) {\n\t\t\t\tfor (IntervalTask intervalTask : taskRegistrar.getFixedRateTaskList()) {\n\t\t\t\t\tif (intervalTask.getRunnable() instanceof ScheduledMethodRunnable) {\n\t\t\t\t\t\tScheduledMethodRunnable runnable = (ScheduledMethodRunnable) intervalTask.getRunnable();\n\t\t\t\t\t\tJobProperty jobProperty = convertToJobProperty(intervalTask, runnable.getTarget(), runnable.getMethod());\n\t\t\t\t\t\tjobs.put(jobProperty.getJobName(), jobProperty);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// 获取仅SchedulerX注解任务\n\t\t\tCollection<Pair<Object, Method>> schedulerXTasks = SchedulerxJobRegister.getInstance().getSchedulerXTaskTargets();\n\t\t\tif (schedulerXTasks != null && schedulerXTasks.size() > 0) {\n\t\t\t\tfor (Pair<Object, Method> task : schedulerXTasks) {\n\t\t\t\t\tJobProperty jobProperty = convertToJobProperty(null, task.getFirst(), task.getSecond());\n\t\t\t\t\tjobs.put(jobProperty.getJobName(), jobProperty);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tjobSyncService.syncJobs(jobs, properties.getNamespaceSource());\n\t\t\tlogger.info(\"spring scheduled job is not empty, sync jobs finished.\");\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tlogger.info(\"spring scheduled job is not empty, sync jobs failed.\", e);\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/java/com/alibaba/cloud/scheduling/schedulerx/util/CronExpression.java",
    "content": "/*\n * Copyright 2024-present the original author or 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\npackage com.alibaba.cloud.scheduling.schedulerx.util;\n\nimport java.text.ParseException;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.SortedSet;\nimport java.util.StringTokenizer;\nimport java.util.TimeZone;\nimport java.util.TreeSet;\n\nimport org.springframework.util.Assert;\n\n/**\n * @author yaohui\n */\npublic final class CronExpression {\n\n\tprotected static final int SECOND = 0;\n\tprotected static final int MINUTE = 1;\n\tprotected static final int HOUR = 2;\n\tprotected static final int DAY_OF_MONTH = 3;\n\tprotected static final int MONTH = 4;\n\tprotected static final int DAY_OF_WEEK = 5;\n\tprotected static final int YEAR = 6;\n\tprotected static final int ALL_SPEC_INT = 99; // '*'\n\tprotected static final int NO_SPEC_INT = 98; // '?'\n\tprotected static final Integer ALL_SPEC = ALL_SPEC_INT;\n\tprotected static final Integer NO_SPEC = NO_SPEC_INT;\n\n\tprotected static final Map<String, Integer> monthMap = new HashMap<>(20);\n\tprotected static final Map<String, Integer> dayMap = new HashMap<>(60);\n\n\tstatic {\n\t\tmonthMap.put(\"JAN\", 0);\n\t\tmonthMap.put(\"FEB\", 1);\n\t\tmonthMap.put(\"MAR\", 2);\n\t\tmonthMap.put(\"APR\", 3);\n\t\tmonthMap.put(\"MAY\", 4);\n\t\tmonthMap.put(\"JUN\", 5);\n\t\tmonthMap.put(\"JUL\", 6);\n\t\tmonthMap.put(\"AUG\", 7);\n\t\tmonthMap.put(\"SEP\", 8);\n\t\tmonthMap.put(\"OCT\", 9);\n\t\tmonthMap.put(\"NOV\", 10);\n\t\tmonthMap.put(\"DEC\", 11);\n\n\t\tdayMap.put(\"SUN\", 1);\n\t\tdayMap.put(\"MON\", 2);\n\t\tdayMap.put(\"TUE\", 3);\n\t\tdayMap.put(\"WED\", 4);\n\t\tdayMap.put(\"THU\", 5);\n\t\tdayMap.put(\"FRI\", 6);\n\t\tdayMap.put(\"SAT\", 7);\n\t}\n\n\tprivate final String cronExpression;\n\tprivate TimeZone timeZone = null;\n\tprotected transient TreeSet<Integer> seconds;\n\tprotected transient TreeSet<Integer> minutes;\n\tprotected transient TreeSet<Integer> hours;\n\tprotected transient TreeSet<Integer> daysOfMonth;\n\tprotected transient TreeSet<Integer> months;\n\tprotected transient TreeSet<Integer> daysOfWeek;\n\tprotected transient TreeSet<Integer> years;\n\n\tprotected transient boolean lastdayOfWeek = false;\n\tprotected transient int nthdayOfWeek = 0;\n\tprotected transient boolean lastdayOfMonth = false;\n\tprotected transient boolean nearestWeekday = false;\n\tprotected transient int lastdayOffset = 0;\n\tprotected transient boolean expressionParsed = false;\n\n\t/**\n\t * MAX_YEAR.\n\t */\n\tpublic static final int MAX_YEAR = Calendar.getInstance().get(Calendar.YEAR) + 100;\n\n\t/**\n\t * MIN_CAL.\n\t */\n\tpublic static final Calendar MIN_CAL = Calendar.getInstance();\n\n\tstatic {\n\t\tMIN_CAL.set(1970, 0, 1);\n\t}\n\n\t/**\n\t * MIN_DATE.\n\t */\n\tpublic static final Date MIN_DATE = MIN_CAL.getTime();\n\n\t/**\n\t * Constructs a new <CODE>CronExpression</CODE> based on the specified\n\t * parameter.\n\t *\n\t * @param cronExpression String representation of the cron expression the\n\t *                       new object should represent\n\t * @throws ParseException if the string expression cannot be parsed into a valid\n\t *                        <CODE>CronExpression</CODE>\n\t */\n\tpublic CronExpression(final String cronExpression) throws ParseException {\n\t\tif (cronExpression == null) {\n\t\t\tthrow new IllegalArgumentException(\"cronExpression cannot be null\");\n\t\t}\n\n\t\tthis.cronExpression = cronExpression.toUpperCase(Locale.US);\n\n\t\tbuildExpression(this.cronExpression);\n\t}\n\n\t/**\n\t * Indicates whether the given date satisfies the cron expression. Note that\n\t * milliseconds are ignored, so two Dates falling on different milliseconds\n\t * of the same second will always have the same result here.\n\t *\n\t * @param date the date to evaluate\n\t * @return a boolean indicating whether the given date satisfies the cron\n\t * expression.\n\t */\n\tpublic boolean isSatisfiedBy(final Date date) {\n\t\tfinal Calendar testDateCal = Calendar.getInstance(getTimeZone());\n\t\ttestDateCal.setTime(date);\n\t\ttestDateCal.set(Calendar.MILLISECOND, 0);\n\t\tfinal Date originalDate = testDateCal.getTime();\n\n\t\ttestDateCal.add(Calendar.SECOND, -1);\n\n\t\tfinal Date timeAfter = getTimeAfter(testDateCal.getTime());\n\n\t\treturn ((timeAfter != null) && (timeAfter.equals(originalDate)));\n\t}\n\n\t/**\n\t * Returns the next date/time <I>after</I> the given date/time which\n\t * satisfies the cron expression.\n\t *\n\t * @param date the date/time at which to begin the search for the next valid\n\t *             date/time\n\t * @return the next valid date/time.\n\t */\n\tpublic Date getNextValidTimeAfter(final Date date) {\n\t\treturn getTimeAfter(date);\n\t}\n\n\t/**\n\t * Returns the next date/time <I>after</I> the given date/time which does\n\t * <I>not</I> satisfy the expression.\n\t *\n\t * @param date the date/time at which to begin the search for the next\n\t *             invalid date/time\n\t * @return the next valid date/time.\n\t */\n\tpublic Date getNextInvalidTimeAfter(final Date date) {\n\t\tlong difference = 1000;\n\n\t\t//move back to the nearest second so differences will be accurate\n\t\tfinal Calendar adjustCal = Calendar.getInstance(getTimeZone());\n\t\tadjustCal.setTime(date);\n\t\tadjustCal.set(Calendar.MILLISECOND, 0);\n\t\tDate lastDate = adjustCal.getTime();\n\n\t\tDate newDate;\n\n\t\t//FUTURE_TODO: (QUARTZ-481) IMPROVE THIS! The following is a BAD solution to this problem. Performance will be very bad here, depending on the cron expression. It is, however A solution.\n\n\t\t//keep getting the next included time until it's farther than one second\n\t\t// apart. At that point, lastDate is the last valid fire time. We return\n\t\t// the second immediately following it.\n\t\twhile (difference == 1000) {\n\t\t\tnewDate = getTimeAfter(lastDate);\n\t\t\tif (newDate == null) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdifference = newDate.getTime() - lastDate.getTime();\n\n\t\t\tif (difference == 1000) {\n\t\t\t\tlastDate = newDate;\n\t\t\t}\n\t\t}\n\n\t\treturn new Date(lastDate.getTime() + 1000);\n\t}\n\n\t/**\n\t * Returns the time zone for which this <code>CronExpression</code>\n\t * will be resolved.\n\t *\n\t * @return the time zone.\n\t */\n\tpublic TimeZone getTimeZone() {\n\t\tif (timeZone == null) {\n\t\t\ttimeZone = TimeZone.getDefault();\n\t\t}\n\n\t\treturn timeZone;\n\t}\n\n\tpublic void setTimeZone(final TimeZone timeZone) {\n\t\tthis.timeZone = timeZone;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn cronExpression;\n\t}\n\n\t/**\n\t * check cron expression is valid or not.\n\t *\n\t * @param cronExpression cron expression\n\t * @return return{@code true}if Cron expression is valid，otherwise return{@code false}.\n\t */\n\tpublic static boolean isValidExpression(final String cronExpression) {\n\t\ttry {\n\t\t\tnew CronExpression(cronExpression);\n\t\t}\n\t\tcatch (final ParseException pe) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic static void validateExpression(final String cronExpression) throws ParseException {\n\t\tnew CronExpression(cronExpression);\n\t}\n\n\tprotected void buildExpression(final String expression) throws ParseException {\n\t\texpressionParsed = true;\n\t\ttry {\n\t\t\tif (seconds == null) {\n\t\t\t\tseconds = new TreeSet<>();\n\t\t\t}\n\t\t\tif (minutes == null) {\n\t\t\t\tminutes = new TreeSet<>();\n\t\t\t}\n\t\t\tif (hours == null) {\n\t\t\t\thours = new TreeSet<>();\n\t\t\t}\n\t\t\tif (daysOfMonth == null) {\n\t\t\t\tdaysOfMonth = new TreeSet<>();\n\t\t\t}\n\t\t\tif (months == null) {\n\t\t\t\tmonths = new TreeSet<>();\n\t\t\t}\n\t\t\tif (daysOfWeek == null) {\n\t\t\t\tdaysOfWeek = new TreeSet<>();\n\t\t\t}\n\t\t\tif (years == null) {\n\t\t\t\tyears = new TreeSet<>();\n\t\t\t}\n\n\t\t\tint exprOn = SECOND;\n\n\t\t\tfinal StringTokenizer exprsTok = new StringTokenizer(expression, \" \\t\",\n\t\t\t\t\tfalse);\n\n\t\t\twhile (exprsTok.hasMoreTokens() && exprOn <= YEAR) {\n\t\t\t\tfinal String expr = exprsTok.nextToken().trim();\n\n\t\t\t\t// throw an exception if L is used with other days of the month\n\t\t\t\tif (exprOn == DAY_OF_MONTH && expr.indexOf('L') != -1 && expr.length() > 1 && expr.contains(\",\")) {\n\t\t\t\t\tthrow new ParseException(\"Support for specifying 'L' and 'LW' with other days of the month is not implemented\", -1);\n\t\t\t\t}\n\t\t\t\t// throw an exception if L is used with other days of the week\n\t\t\t\tif (exprOn == DAY_OF_WEEK && expr.indexOf('L') != -1 && expr.length() > 1 && expr.contains(\",\")) {\n\t\t\t\t\tthrow new ParseException(\"Support for specifying 'L' with other days of the week is not implemented\", -1);\n\t\t\t\t}\n\t\t\t\tif (exprOn == DAY_OF_WEEK && expr.indexOf('#') != -1 && expr.indexOf('#', expr.indexOf('#') + 1) != -1) {\n\t\t\t\t\tthrow new ParseException(\"Support for specifying multiple \\\"nth\\\" days is not implemented.\", -1);\n\t\t\t\t}\n\n\t\t\t\tfinal StringTokenizer vTok = new StringTokenizer(expr, \",\");\n\t\t\t\twhile (vTok.hasMoreTokens()) {\n\t\t\t\t\tfinal String v = vTok.nextToken();\n\t\t\t\t\tstoreExpressionVals(0, v, exprOn);\n\t\t\t\t}\n\n\t\t\t\texprOn++;\n\t\t\t}\n\n\t\t\tif (exprOn <= DAY_OF_WEEK) {\n\t\t\t\tthrow new ParseException(\"Unexpected end of expression.\",\n\t\t\t\t\t\texpression.length());\n\t\t\t}\n\n\t\t\tif (exprOn <= YEAR) {\n\t\t\t\tstoreExpressionVals(0, \"*\", YEAR);\n\t\t\t}\n\n\t\t\tfinal TreeSet<Integer> dow = getSet(DAY_OF_WEEK);\n\t\t\tfinal TreeSet<Integer> dom = getSet(DAY_OF_MONTH);\n\n\t\t\t// Copying the logic from the UnsupportedOperationException below\n\t\t\tfinal boolean dayOfMSpec = !dom.contains(NO_SPEC);\n\t\t\tfinal boolean dayOfWSpec = !dow.contains(NO_SPEC);\n\n\t\t\tif (!dayOfMSpec || dayOfWSpec) {\n\t\t\t\tif (!dayOfWSpec || dayOfMSpec) {\n\t\t\t\t\tthrow new ParseException(\n\t\t\t\t\t\t\t\"Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.\", 0);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcatch (final ParseException pe) {\n\t\t\tthrow pe;\n\t\t}\n\t\tcatch (final Exception e) {\n\t\t\tthrow new ParseException(\"Illegal cron expression format (\"\n\t\t\t\t\t+ e.toString() + \")\", 0);\n\t\t}\n\t}\n\n\tprotected int storeExpressionVals(final int pos, final String s, final int type)\n\t\t\tthrows ParseException {\n\n\t\tint incr = 0;\n\t\tint i = skipWhiteSpace(pos, s);\n\t\tif (i >= s.length()) {\n\t\t\treturn i;\n\t\t}\n\t\tchar c = s.charAt(i);\n\t\tif ((c >= 'A') && (c <= 'Z') && (!s.equals(\"L\")) && (!s.equals(\"LW\")) && (!s.matches(\"^L-[0-9]*[W]?\"))) {\n\t\t\tString sub = s.substring(i, i + 3);\n\t\t\tint sval = -1;\n\t\t\tint eval = -1;\n\t\t\tif (type == MONTH) {\n\t\t\t\tsval = getMonthNumber(sub) + 1;\n\t\t\t\tif (sval <= 0) {\n\t\t\t\t\tthrow new ParseException(\"Invalid Month value: '\" + sub + \"'\", i);\n\t\t\t\t}\n\t\t\t\tif (s.length() > i + 3 && (s.charAt(i + 3) == '-')) {\n\t\t\t\t\ti += 4;\n\t\t\t\t\tsub = s.substring(i, i + 3);\n\t\t\t\t\teval = getMonthNumber(sub) + 1;\n\t\t\t\t\tAssert.isTrue(eval > 0, \"Invalid Month value: '\" + sub + \"'\");\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (type == DAY_OF_WEEK) {\n\t\t\t\tsval = getDayOfWeekNumber(sub);\n\t\t\t\tif (sval < 0) {\n\t\t\t\t\tthrow new ParseException(\"Invalid Day-of-Week value: '\"\n\t\t\t\t\t\t\t+ sub + \"'\", i);\n\t\t\t\t}\n\t\t\t\tif (s.length() > i + 3) {\n\t\t\t\t\tc = s.charAt(i + 3);\n\t\t\t\t\tif (c == '-') {\n\t\t\t\t\t\ti += 4;\n\t\t\t\t\t\tsub = s.substring(i, i + 3);\n\t\t\t\t\t\teval = getDayOfWeekNumber(sub);\n\t\t\t\t\t\tAssert.isTrue(eval >= 0, \"Invalid Day-of-Week value: '\" + sub + \"'\");\n\t\t\t\t\t}\n\t\t\t\t\telse if (c == '#') {\n\t\t\t\t\t\ti += 4;\n\t\t\t\t\t\tnthdayOfWeek = Integer.parseInt(s.substring(i));\n\t\t\t\t\t\tAssert.isTrue(nthdayOfWeek > 0 && nthdayOfWeek < 6, \"A numeric value between 1 and 5 must follow the '#' option\");\n\t\t\t\t\t}\n\t\t\t\t\telse if (c == 'L') {\n\t\t\t\t\t\tlastdayOfWeek = true;\n\t\t\t\t\t\ti++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new ParseException(\n\t\t\t\t\t\t\"Illegal characters for this position: '\" + sub + \"'\",\n\t\t\t\t\t\ti);\n\t\t\t}\n\t\t\tif (eval != -1) {\n\t\t\t\tincr = 1;\n\t\t\t}\n\t\t\taddToSet(sval, eval, incr, type);\n\t\t\treturn (i + 3);\n\t\t}\n\n\t\tif (c == '?') {\n\t\t\ti++;\n\t\t\tif ((i + 1) < s.length()\n\t\t\t\t\t&& (s.charAt(i) != ' ' && s.charAt(i + 1) != '\\t')) {\n\t\t\t\tthrow new ParseException(\"Illegal character after '?': \"\n\t\t\t\t\t\t+ s.charAt(i), i);\n\t\t\t}\n\t\t\tif (type != DAY_OF_WEEK && type != DAY_OF_MONTH) {\n\t\t\t\tthrow new ParseException(\n\t\t\t\t\t\t\"'?' can only be specfied for Day-of-Month or Day-of-Week.\",\n\t\t\t\t\t\ti);\n\t\t\t}\n\t\t\tif (type == DAY_OF_WEEK && !lastdayOfMonth) {\n\t\t\t\tfinal int val = daysOfMonth.last();\n\t\t\t\tif (val == NO_SPEC_INT) {\n\t\t\t\t\tthrow new ParseException(\n\t\t\t\t\t\t\t\"'?' can only be specfied for Day-of-Month -OR- Day-of-Week.\",\n\t\t\t\t\t\t\ti);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\taddToSet(NO_SPEC_INT, -1, 0, type);\n\t\t\treturn i;\n\t\t}\n\n\t\tif (c == '*' || c == '/') {\n\t\t\tif (c == '*' && (i + 1) >= s.length()) {\n\t\t\t\taddToSet(ALL_SPEC_INT, -1, incr, type);\n\t\t\t\treturn i + 1;\n\t\t\t}\n\t\t\telse if (c == '/'\n\t\t\t\t\t&& ((i + 1) >= s.length() || s.charAt(i + 1) == ' ' || s\n\t\t\t\t\t.charAt(i + 1) == '\\t')) {\n\t\t\t\tthrow new ParseException(\"'/' must be followed by an integer.\", i);\n\t\t\t}\n\t\t\telse if (c == '*') {\n\t\t\t\ti++;\n\t\t\t}\n\t\t\tc = s.charAt(i);\n\t\t\tif (c == '/') { // is an increment specified?\n\t\t\t\ti++;\n\t\t\t\tif (i >= s.length()) {\n\t\t\t\t\tthrow new ParseException(\"Unexpected end of string.\", i);\n\t\t\t\t}\n\n\t\t\t\tincr = getNumericValue(s, i);\n\n\t\t\t\ti++;\n\t\t\t\tif (incr > 10) {\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t\tif (incr > 59 && (type == SECOND || type == MINUTE)) {\n\t\t\t\t\tthrow new ParseException(\"Increment > 60 : \" + incr, i);\n\t\t\t\t}\n\t\t\t\telse if (incr > 23 && (type == HOUR)) {\n\t\t\t\t\tthrow new ParseException(\"Increment > 24 : \" + incr, i);\n\t\t\t\t}\n\t\t\t\telse if (incr > 31 && (type == DAY_OF_MONTH)) {\n\t\t\t\t\tthrow new ParseException(\"Increment > 31 : \" + incr, i);\n\t\t\t\t}\n\t\t\t\telse if (incr > 7 && (type == DAY_OF_WEEK)) {\n\t\t\t\t\tthrow new ParseException(\"Increment > 7 : \" + incr, i);\n\t\t\t\t}\n\t\t\t\telse if (incr > 12 && (type == MONTH)) {\n\t\t\t\t\tthrow new ParseException(\"Increment > 12 : \" + incr, i);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tincr = 1;\n\t\t\t}\n\n\t\t\taddToSet(ALL_SPEC_INT, -1, incr, type);\n\t\t\treturn i;\n\t\t}\n\t\telse if (c == 'L') {\n\t\t\ti++;\n\t\t\tif (type == DAY_OF_MONTH) {\n\t\t\t\tlastdayOfMonth = true;\n\t\t\t}\n\t\t\tif (type == DAY_OF_WEEK) {\n\t\t\t\taddToSet(7, 7, 0, type);\n\t\t\t}\n\t\t\tif (type == DAY_OF_MONTH && s.length() > i) {\n\t\t\t\tc = s.charAt(i);\n\t\t\t\tif (c == '-') {\n\t\t\t\t\tfinal ValueSet vs = getValue(0, s, i + 1);\n\t\t\t\t\tlastdayOffset = vs.value;\n\t\t\t\t\tif (lastdayOffset > 30) {\n\t\t\t\t\t\tthrow new ParseException(\"Offset from last day must be <= 30\", i + 1);\n\t\t\t\t\t}\n\t\t\t\t\ti = vs.pos;\n\t\t\t\t}\n\t\t\t\tif (s.length() > i) {\n\t\t\t\t\tc = s.charAt(i);\n\t\t\t\t\tif (c == 'W') {\n\t\t\t\t\t\tnearestWeekday = true;\n\t\t\t\t\t\ti++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn i;\n\t\t}\n\t\telse if (c >= '0' && c <= '9') {\n\t\t\tint val = Integer.parseInt(String.valueOf(c));\n\t\t\ti++;\n\t\t\tif (i >= s.length()) {\n\t\t\t\taddToSet(val, -1, -1, type);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tc = s.charAt(i);\n\t\t\t\tif (c >= '0' && c <= '9') {\n\t\t\t\t\tfinal ValueSet vs = getValue(val, s, i);\n\t\t\t\t\tval = vs.value;\n\t\t\t\t\ti = vs.pos;\n\t\t\t\t}\n\t\t\t\ti = checkNext(i, s, val, type);\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tthrow new ParseException(\"Unexpected character: \" + c, i);\n\t\t}\n\n\t\treturn i;\n\t}\n\n\tprotected int checkNext(final int pos, final String s, final int val, final int type)\n\t\t\tthrows ParseException {\n\n\t\tint end = -1;\n\t\tint i = pos;\n\n\t\tif (i >= s.length()) {\n\t\t\taddToSet(val, end, -1, type);\n\t\t\treturn i;\n\t\t}\n\n\t\tchar c = s.charAt(pos);\n\n\t\tif (c == 'L') {\n\t\t\tif (type == DAY_OF_WEEK) {\n\t\t\t\tif (val < 1 || val > 7) {\n\t\t\t\t\tthrow new ParseException(\"Day-of-Week values must be between 1 and 7\", -1);\n\t\t\t\t}\n\t\t\t\tlastdayOfWeek = true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new ParseException(\"'L' option is not valid here. (pos=\" + i + \")\", i);\n\t\t\t}\n\t\t\tfinal TreeSet<Integer> set = getSet(type);\n\t\t\tset.add(val);\n\t\t\ti++;\n\t\t\treturn i;\n\t\t}\n\n\t\tif (c == 'W') {\n\t\t\tif (type == DAY_OF_MONTH) {\n\t\t\t\tnearestWeekday = true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new ParseException(\"'W' option is not valid here. (pos=\" + i + \")\", i);\n\t\t\t}\n\t\t\tif (val > 31) {\n\t\t\t\tthrow new ParseException(\"The 'W' option does not make sense with values larger than 31 (max number of days in a month)\", i);\n\t\t\t}\n\t\t\tfinal TreeSet<Integer> set = getSet(type);\n\t\t\tset.add(val);\n\t\t\ti++;\n\t\t\treturn i;\n\t\t}\n\n\t\tif (c == '#') {\n\t\t\tif (type != DAY_OF_WEEK) {\n\t\t\t\tthrow new ParseException(\"'#' option is not valid here. (pos=\" + i + \")\", i);\n\t\t\t}\n\t\t\ti++;\n\t\t\ttry {\n\t\t\t\tnthdayOfWeek = Integer.parseInt(s.substring(i));\n\t\t\t\tif (nthdayOfWeek < 1 || nthdayOfWeek > 5) {\n\t\t\t\t\tthrow new Exception();\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (final Exception e) {\n\t\t\t\tthrow new ParseException(\n\t\t\t\t\t\t\"A numeric value between 1 and 5 must follow the '#' option\",\n\t\t\t\t\t\ti);\n\t\t\t}\n\n\t\t\tfinal TreeSet<Integer> set = getSet(type);\n\t\t\tset.add(val);\n\t\t\ti++;\n\t\t\treturn i;\n\t\t}\n\n\t\tif (c == '-') {\n\t\t\ti++;\n\t\t\tc = s.charAt(i);\n\t\t\tfinal int v = Integer.parseInt(String.valueOf(c));\n\t\t\tend = v;\n\t\t\ti++;\n\t\t\tif (i >= s.length()) {\n\t\t\t\taddToSet(val, end, 1, type);\n\t\t\t\treturn i;\n\t\t\t}\n\t\t\tc = s.charAt(i);\n\t\t\tif (c >= '0' && c <= '9') {\n\t\t\t\tfinal ValueSet vs = getValue(v, s, i);\n\t\t\t\tend = vs.value;\n\t\t\t\ti = vs.pos;\n\t\t\t}\n\t\t\tif (i < s.length() && (s.charAt(i) == '/')) {\n\t\t\t\ti++;\n\t\t\t\tc = s.charAt(i);\n\t\t\t\tfinal int v2 = Integer.parseInt(String.valueOf(c));\n\t\t\t\ti++;\n\t\t\t\tif (i >= s.length()) {\n\t\t\t\t\taddToSet(val, end, v2, type);\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t\tc = s.charAt(i);\n\t\t\t\tif (c >= '0' && c <= '9') {\n\t\t\t\t\tfinal ValueSet vs = getValue(v2, s, i);\n\t\t\t\t\tfinal int v3 = vs.value;\n\t\t\t\t\taddToSet(val, end, v3, type);\n\t\t\t\t\ti = vs.pos;\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\taddToSet(val, end, v2, type);\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\taddToSet(val, end, 1, type);\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\n\t\tif (c == '/') {\n\t\t\ti++;\n\t\t\tc = s.charAt(i);\n\t\t\tfinal int v2 = Integer.parseInt(String.valueOf(c));\n\t\t\ti++;\n\t\t\tif (i >= s.length()) {\n\t\t\t\taddToSet(val, end, v2, type);\n\t\t\t\treturn i;\n\t\t\t}\n\t\t\tc = s.charAt(i);\n\t\t\tif (c >= '0' && c <= '9') {\n\t\t\t\tfinal ValueSet vs = getValue(v2, s, i);\n\t\t\t\tfinal int v3 = vs.value;\n\t\t\t\taddToSet(val, end, v3, type);\n\t\t\t\ti = vs.pos;\n\t\t\t\treturn i;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new ParseException(\"Unexpected character '\" + c + \"' after '/'\", i);\n\t\t\t}\n\t\t}\n\n\t\taddToSet(val, end, 0, type);\n\t\ti++;\n\t\treturn i;\n\t}\n\n\tpublic String getCronExpression() {\n\t\treturn cronExpression;\n\t}\n\n\tpublic String getExpressionSummary() {\n\t\tfinal StringBuilder buf = new StringBuilder();\n\n\t\tbuf.append(\"seconds: \");\n\t\tbuf.append(getExpressionSetSummary(seconds));\n\t\tbuf.append(\"\\n\");\n\t\tbuf.append(\"minutes: \");\n\t\tbuf.append(getExpressionSetSummary(minutes));\n\t\tbuf.append(\"\\n\");\n\t\tbuf.append(\"hours: \");\n\t\tbuf.append(getExpressionSetSummary(hours));\n\t\tbuf.append(\"\\n\");\n\t\tbuf.append(\"daysOfMonth: \");\n\t\tbuf.append(getExpressionSetSummary(daysOfMonth));\n\t\tbuf.append(\"\\n\");\n\t\tbuf.append(\"months: \");\n\t\tbuf.append(getExpressionSetSummary(months));\n\t\tbuf.append(\"\\n\");\n\t\tbuf.append(\"daysOfWeek: \");\n\t\tbuf.append(getExpressionSetSummary(daysOfWeek));\n\t\tbuf.append(\"\\n\");\n\t\tbuf.append(\"lastdayOfWeek: \");\n\t\tbuf.append(lastdayOfWeek);\n\t\tbuf.append(\"\\n\");\n\t\tbuf.append(\"nearestWeekday: \");\n\t\tbuf.append(nearestWeekday);\n\t\tbuf.append(\"\\n\");\n\t\tbuf.append(\"NthDayOfWeek: \");\n\t\tbuf.append(nthdayOfWeek);\n\t\tbuf.append(\"\\n\");\n\t\tbuf.append(\"lastdayOfMonth: \");\n\t\tbuf.append(lastdayOfMonth);\n\t\tbuf.append(\"\\n\");\n\t\tbuf.append(\"years: \");\n\t\tbuf.append(getExpressionSetSummary(years));\n\t\tbuf.append(\"\\n\");\n\n\t\treturn buf.toString();\n\t}\n\n\tprotected String getExpressionSetSummary(final java.util.Set<Integer> set) {\n\n\t\tif (set.contains(NO_SPEC)) {\n\t\t\treturn \"?\";\n\t\t}\n\t\tif (set.contains(ALL_SPEC)) {\n\t\t\treturn \"*\";\n\t\t}\n\n\t\tfinal StringBuilder buf = new StringBuilder();\n\n\t\tfinal Iterator<Integer> itr = set.iterator();\n\t\tboolean first = true;\n\t\twhile (itr.hasNext()) {\n\t\t\tfinal Integer iVal = itr.next();\n\t\t\tfinal String val = iVal.toString();\n\t\t\tif (!first) {\n\t\t\t\tbuf.append(\",\");\n\t\t\t}\n\t\t\tbuf.append(val);\n\t\t\tfirst = false;\n\t\t}\n\n\t\treturn buf.toString();\n\t}\n\n\tprotected String getExpressionSetSummary(final java.util.ArrayList<Integer> list) {\n\n\t\tif (list.contains(NO_SPEC)) {\n\t\t\treturn \"?\";\n\t\t}\n\t\tif (list.contains(ALL_SPEC)) {\n\t\t\treturn \"*\";\n\t\t}\n\n\t\tfinal StringBuilder buf = new StringBuilder();\n\n\t\tfinal Iterator<Integer> itr = list.iterator();\n\t\tboolean first = true;\n\t\twhile (itr.hasNext()) {\n\t\t\tfinal Integer iVal = itr.next();\n\t\t\tfinal String val = iVal.toString();\n\t\t\tif (!first) {\n\t\t\t\tbuf.append(\",\");\n\t\t\t}\n\t\t\tbuf.append(val);\n\t\t\tfirst = false;\n\t\t}\n\n\t\treturn buf.toString();\n\t}\n\n\tprotected int skipWhiteSpace(int i, final String s) {\n\t\tfor (; i < s.length() && (s.charAt(i) == ' ' || s.charAt(i) == '\\t'); i++) {\n\t\t\t// empty\n\t\t}\n\n\t\treturn i;\n\t}\n\n\tprotected int findNextWhiteSpace(int i, final String s) {\n\t\tfor (; i < s.length() && (s.charAt(i) != ' ' || s.charAt(i) != '\\t'); i++) {\n\t\t\t// empty\n\t\t}\n\n\t\treturn i;\n\t}\n\n\tprotected void addToSet(final int val, final int end, int incr, final int type)\n\t\t\tthrows ParseException {\n\n\t\tfinal TreeSet<Integer> set = getSet(type);\n\n\t\tif (type == SECOND || type == MINUTE) {\n\t\t\tif ((val < 0 || val > 59 || end > 59) && (val != ALL_SPEC_INT)) {\n\t\t\t\tthrow new ParseException(\n\t\t\t\t\t\t\"Minute and Second values must be between 0 and 59\",\n\t\t\t\t\t\t-1);\n\t\t\t}\n\t\t}\n\t\telse if (type == HOUR) {\n\t\t\tif ((val < 0 || val > 23 || end > 23) && (val != ALL_SPEC_INT)) {\n\t\t\t\tthrow new ParseException(\n\t\t\t\t\t\t\"Hour values must be between 0 and 23\", -1);\n\t\t\t}\n\t\t}\n\t\telse if (type == DAY_OF_MONTH) {\n\t\t\tif ((val < 1 || val > 31 || end > 31) && (val != ALL_SPEC_INT)\n\t\t\t\t\t&& (val != NO_SPEC_INT)) {\n\t\t\t\tthrow new ParseException(\n\t\t\t\t\t\t\"Day of month values must be between 1 and 31\", -1);\n\t\t\t}\n\t\t}\n\t\telse if (type == MONTH) {\n\t\t\tif ((val < 1 || val > 12 || end > 12) && (val != ALL_SPEC_INT)) {\n\t\t\t\tthrow new ParseException(\n\t\t\t\t\t\t\"Month values must be between 1 and 12\", -1);\n\t\t\t}\n\t\t}\n\t\telse if (type == DAY_OF_WEEK) {\n\t\t\tif ((val == 0 || val > 7 || end > 7) && (val != ALL_SPEC_INT)\n\t\t\t\t\t&& (val != NO_SPEC_INT)) {\n\t\t\t\tthrow new ParseException(\n\t\t\t\t\t\t\"Day-of-Week values must be between 1 and 7\", -1);\n\t\t\t}\n\t\t}\n\n\t\tif ((incr == 0 || incr == -1) && val != ALL_SPEC_INT) {\n\t\t\tif (val != -1) {\n\t\t\t\tset.add(val);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tset.add(NO_SPEC);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tint startAt = val;\n\t\tint stopAt = end;\n\n\t\tif (val == ALL_SPEC_INT && incr <= 0) {\n\t\t\tincr = 1;\n\t\t\tset.add(ALL_SPEC); // put in a marker, but also fill values\n\t\t}\n\n\t\tif (type == SECOND || type == MINUTE) {\n\t\t\tif (stopAt == -1) {\n\t\t\t\tstopAt = 59;\n\t\t\t}\n\t\t\tif (startAt == -1 || startAt == ALL_SPEC_INT) {\n\t\t\t\tstartAt = 0;\n\t\t\t}\n\t\t}\n\t\telse if (type == HOUR) {\n\t\t\tif (stopAt == -1) {\n\t\t\t\tstopAt = 23;\n\t\t\t}\n\t\t\tif (startAt == -1 || startAt == ALL_SPEC_INT) {\n\t\t\t\tstartAt = 0;\n\t\t\t}\n\t\t}\n\t\telse if (type == DAY_OF_MONTH) {\n\t\t\tif (stopAt == -1) {\n\t\t\t\tstopAt = 31;\n\t\t\t}\n\t\t\tif (startAt == -1 || startAt == ALL_SPEC_INT) {\n\t\t\t\tstartAt = 1;\n\t\t\t}\n\t\t}\n\t\telse if (type == MONTH) {\n\t\t\tif (stopAt == -1) {\n\t\t\t\tstopAt = 12;\n\t\t\t}\n\t\t\tif (startAt == -1 || startAt == ALL_SPEC_INT) {\n\t\t\t\tstartAt = 1;\n\t\t\t}\n\t\t}\n\t\telse if (type == DAY_OF_WEEK) {\n\t\t\tif (stopAt == -1) {\n\t\t\t\tstopAt = 7;\n\t\t\t}\n\t\t\tif (startAt == -1 || startAt == ALL_SPEC_INT) {\n\t\t\t\tstartAt = 1;\n\t\t\t}\n\t\t}\n\t\telse if (type == YEAR) {\n\t\t\tif (stopAt == -1) {\n\t\t\t\tstopAt = MAX_YEAR;\n\t\t\t}\n\t\t\tif (startAt == -1 || startAt == ALL_SPEC_INT) {\n\t\t\t\tstartAt = 1970;\n\t\t\t}\n\t\t}\n\n\t\t// if the end of the range is before the start, then we need to overflow into\n\t\t// the next day, month etc. This is done by adding the maximum amount for that\n\t\t// type, and using modulus max to determine the value being added.\n\t\tint max = -1;\n\t\tif (stopAt < startAt) {\n\t\t\tswitch (type) {\n\t\t\t\tcase SECOND:\n\t\t\t\t\tmax = 60;\n\t\t\t\t\tbreak;\n\t\t\t\tcase MINUTE:\n\t\t\t\t\tmax = 60;\n\t\t\t\t\tbreak;\n\t\t\t\tcase HOUR:\n\t\t\t\t\tmax = 24;\n\t\t\t\t\tbreak;\n\t\t\t\tcase MONTH:\n\t\t\t\t\tmax = 12;\n\t\t\t\t\tbreak;\n\t\t\t\tcase DAY_OF_WEEK:\n\t\t\t\t\tmax = 7;\n\t\t\t\t\tbreak;\n\t\t\t\tcase DAY_OF_MONTH:\n\t\t\t\t\tmax = 31;\n\t\t\t\t\tbreak;\n\t\t\t\tcase YEAR:\n\t\t\t\t\tthrow new IllegalArgumentException(\"Start year must be less than stop year\");\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new IllegalArgumentException(\"Unexpected type encountered\");\n\t\t\t}\n\t\t\tstopAt += max;\n\t\t}\n\n\t\tfor (int i = startAt; i <= stopAt; i += incr) {\n\t\t\tif (max == -1) {\n\t\t\t\t// ie: there's no max to overflow over\n\t\t\t\tset.add(i);\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// take the modulus to get the real value\n\t\t\t\tint i2 = i % max;\n\n\t\t\t\t// 1-indexed ranges should not include 0, and should include their max\n\t\t\t\tif (i2 == 0 && (type == MONTH || type == DAY_OF_WEEK || type == DAY_OF_MONTH)) {\n\t\t\t\t\ti2 = max;\n\t\t\t\t}\n\n\t\t\t\tset.add(i2);\n\t\t\t}\n\t\t}\n\t}\n\n\tTreeSet<Integer> getSet(final int type) throws ParseException {\n\t\tswitch (type) {\n\t\t\tcase SECOND:\n\t\t\t\treturn seconds;\n\t\t\tcase MINUTE:\n\t\t\t\treturn minutes;\n\t\t\tcase HOUR:\n\t\t\t\treturn hours;\n\t\t\tcase DAY_OF_MONTH:\n\t\t\t\treturn daysOfMonth;\n\t\t\tcase MONTH:\n\t\t\t\treturn months;\n\t\t\tcase DAY_OF_WEEK:\n\t\t\t\treturn daysOfWeek;\n\t\t\tcase YEAR:\n\t\t\t\treturn years;\n\t\t\tdefault:\n\t\t\t\tthrow new ParseException(\"Invalid type value: '\" + type + \"'\", -1);\n\t\t}\n\t}\n\n\tprotected ValueSet getValue(final int v, final String s, int i) {\n\t\tchar c = s.charAt(i);\n\t\tfinal StringBuilder s1 = new StringBuilder(String.valueOf(v));\n\t\twhile (c >= '0' && c <= '9') {\n\t\t\ts1.append(c);\n\t\t\ti++;\n\t\t\tif (i >= s.length()) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tc = s.charAt(i);\n\t\t}\n\t\tfinal ValueSet val = new ValueSet();\n\n\t\tval.pos = (i < s.length()) ? i : i + 1;\n\t\tval.value = Integer.parseInt(s1.toString());\n\t\treturn val;\n\t}\n\n\tprotected int getNumericValue(final String s, final int i) {\n\t\tfinal int endOfVal = findNextWhiteSpace(i, s);\n\t\tfinal String val = s.substring(i, endOfVal);\n\t\treturn Integer.parseInt(val);\n\t}\n\n\tprotected int getMonthNumber(final String s) {\n\t\tfinal Integer integer = monthMap.get(s);\n\n\t\tif (integer == null) {\n\t\t\treturn -1;\n\t\t}\n\n\t\treturn integer;\n\t}\n\n\tprotected int getDayOfWeekNumber(final String s) {\n\t\tfinal Integer integer = dayMap.get(s);\n\n\t\tif (integer == null) {\n\t\t\treturn -1;\n\t\t}\n\n\t\treturn integer;\n\t}\n\n\tpublic Date getTimeAfter(Date afterTime) {\n\n\t\t// Computation is based on Gregorian year only.\n\t\tfinal Calendar cl = new java.util.GregorianCalendar(getTimeZone());\n\n\t\t// move ahead one second, since we're computing the time *after* the\n\t\t// given time\n\t\tif (afterTime == null) {\n\t\t\treturn null;\n\t\t}\n\t\tafterTime = new Date(afterTime.getTime() + 1000);\n\t\t// CronTrigger does not deal with milliseconds\n\t\tcl.setTime(afterTime);\n\t\tcl.set(Calendar.MILLISECOND, 0);\n\n\t\tboolean gotOne = false;\n\t\t// loop until we've computed the next time, or we've past the endTime\n\t\twhile (!gotOne) {\n\t\t\t//if (endTime != null && cl.getTime().after(endTime)) return null;\n\t\t\tif (cl.get(Calendar.YEAR) > 2999) { // prevent endless loop...\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tSortedSet<Integer> st = null;\n\t\t\tint t = 0;\n\n\t\t\tint sec = cl.get(Calendar.SECOND);\n\t\t\tint min = cl.get(Calendar.MINUTE);\n\n\t\t\t// get second.................................................\n\t\t\tst = seconds.tailSet(sec);\n\t\t\tif (st != null && st.size() != 0) {\n\t\t\t\tsec = st.first();\n\t\t\t}\n\t\t\telse {\n\t\t\t\tsec = seconds.first();\n\t\t\t\tmin++;\n\t\t\t\tcl.set(Calendar.MINUTE, min);\n\t\t\t}\n\t\t\tcl.set(Calendar.SECOND, sec);\n\n\t\t\tmin = cl.get(Calendar.MINUTE);\n\t\t\tint hr = cl.get(Calendar.HOUR_OF_DAY);\n\t\t\tt = -1;\n\n\t\t\t// get minute.................................................\n\t\t\tst = minutes.tailSet(min);\n\t\t\tif (st != null && st.size() != 0) {\n\t\t\t\tt = min;\n\t\t\t\tmin = st.first();\n\t\t\t}\n\t\t\telse {\n\t\t\t\tmin = minutes.first();\n\t\t\t\thr++;\n\t\t\t}\n\t\t\tif (min != t) {\n\t\t\t\tcl.set(Calendar.SECOND, 0);\n\t\t\t\tcl.set(Calendar.MINUTE, min);\n\t\t\t\tsetCalendarHour(cl, hr);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcl.set(Calendar.MINUTE, min);\n\n\t\t\thr = cl.get(Calendar.HOUR_OF_DAY);\n\t\t\tint day = cl.get(Calendar.DAY_OF_MONTH);\n\t\t\tt = -1;\n\n\t\t\t// get hour...................................................\n\t\t\tst = hours.tailSet(hr);\n\t\t\tif (st != null && st.size() != 0) {\n\t\t\t\tt = hr;\n\t\t\t\thr = st.first();\n\t\t\t}\n\t\t\telse {\n\t\t\t\thr = hours.first();\n\t\t\t\tday++;\n\t\t\t}\n\t\t\tif (hr != t) {\n\t\t\t\tcl.set(Calendar.SECOND, 0);\n\t\t\t\tcl.set(Calendar.MINUTE, 0);\n\t\t\t\tcl.set(Calendar.DAY_OF_MONTH, day);\n\t\t\t\tsetCalendarHour(cl, hr);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcl.set(Calendar.HOUR_OF_DAY, hr);\n\n\t\t\tday = cl.get(Calendar.DAY_OF_MONTH);\n\t\t\tint mon = cl.get(Calendar.MONTH) + 1;\n\t\t\t// '+ 1' because calendar is 0-based for this field, and we are\n\t\t\t// 1-based\n\t\t\tt = -1;\n\t\t\tint tmon = mon;\n\n\t\t\t// get day...................................................\n\t\t\tfinal boolean dayOfMSpec = !daysOfMonth.contains(NO_SPEC);\n\t\t\tfinal boolean dayOfWSpec = !daysOfWeek.contains(NO_SPEC);\n\t\t\tif (dayOfMSpec && !dayOfWSpec) { // get day by day of month rule\n\t\t\t\tst = daysOfMonth.tailSet(day);\n\t\t\t\tif (lastdayOfMonth) {\n\t\t\t\t\tif (!nearestWeekday) {\n\t\t\t\t\t\tt = day;\n\t\t\t\t\t\tday = getLastDayOfMonth(mon, cl.get(Calendar.YEAR));\n\t\t\t\t\t\tday -= lastdayOffset;\n\t\t\t\t\t\tday = t > day ? 1 : day;\n\t\t\t\t\t\tif (t > day && ++mon > 12) {\n\t\t\t\t\t\t\tmon = 1;\n\t\t\t\t\t\t\ttmon = 3333; // ensure test of mon != tmon further below fails\n\t\t\t\t\t\t\tcl.add(Calendar.YEAR, 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tt = day;\n\t\t\t\t\t\tday = getLastDayOfMonth(mon, cl.get(Calendar.YEAR));\n\t\t\t\t\t\tday -= lastdayOffset;\n\n\t\t\t\t\t\tfinal Calendar tcal = Calendar.getInstance(getTimeZone());\n\t\t\t\t\t\ttcal.set(Calendar.SECOND, 0);\n\t\t\t\t\t\ttcal.set(Calendar.MINUTE, 0);\n\t\t\t\t\t\ttcal.set(Calendar.HOUR_OF_DAY, 0);\n\t\t\t\t\t\ttcal.set(Calendar.DAY_OF_MONTH, day);\n\t\t\t\t\t\ttcal.set(Calendar.MONTH, mon - 1);\n\t\t\t\t\t\ttcal.set(Calendar.YEAR, cl.get(Calendar.YEAR));\n\n\t\t\t\t\t\tfinal int ldom = getLastDayOfMonth(mon, cl.get(Calendar.YEAR));\n\t\t\t\t\t\tfinal int dow = tcal.get(Calendar.DAY_OF_WEEK);\n\n\t\t\t\t\t\tif (dow == Calendar.SATURDAY && day == 1) {\n\t\t\t\t\t\t\tday += 2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (dow == Calendar.SATURDAY) {\n\t\t\t\t\t\t\tday -= 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (dow == Calendar.SUNDAY && day == ldom) {\n\t\t\t\t\t\t\tday -= 2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (dow == Calendar.SUNDAY) {\n\t\t\t\t\t\t\tday += 1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttcal.set(Calendar.SECOND, sec);\n\t\t\t\t\t\ttcal.set(Calendar.MINUTE, min);\n\t\t\t\t\t\ttcal.set(Calendar.HOUR_OF_DAY, hr);\n\t\t\t\t\t\ttcal.set(Calendar.DAY_OF_MONTH, day);\n\t\t\t\t\t\ttcal.set(Calendar.MONTH, mon - 1);\n\t\t\t\t\t\tfinal Date nTime = tcal.getTime();\n\t\t\t\t\t\tif (nTime.before(afterTime)) {\n\t\t\t\t\t\t\tday = 1;\n\t\t\t\t\t\t\tmon++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (nearestWeekday) {\n\t\t\t\t\tt = day;\n\t\t\t\t\tday = daysOfMonth.first();\n\n\t\t\t\t\tfinal Calendar tcal = Calendar.getInstance(getTimeZone());\n\t\t\t\t\ttcal.set(Calendar.SECOND, 0);\n\t\t\t\t\ttcal.set(Calendar.MINUTE, 0);\n\t\t\t\t\ttcal.set(Calendar.HOUR_OF_DAY, 0);\n\t\t\t\t\ttcal.set(Calendar.DAY_OF_MONTH, day);\n\t\t\t\t\ttcal.set(Calendar.MONTH, mon - 1);\n\t\t\t\t\ttcal.set(Calendar.YEAR, cl.get(Calendar.YEAR));\n\n\t\t\t\t\tfinal int ldom = getLastDayOfMonth(mon, cl.get(Calendar.YEAR));\n\t\t\t\t\tfinal int dow = tcal.get(Calendar.DAY_OF_WEEK);\n\n\t\t\t\t\tif (dow == Calendar.SATURDAY && day == 1) {\n\t\t\t\t\t\tday += 2;\n\t\t\t\t\t}\n\t\t\t\t\telse if (dow == Calendar.SATURDAY) {\n\t\t\t\t\t\tday -= 1;\n\t\t\t\t\t}\n\t\t\t\t\telse if (dow == Calendar.SUNDAY && day == ldom) {\n\t\t\t\t\t\tday -= 2;\n\t\t\t\t\t}\n\t\t\t\t\telse if (dow == Calendar.SUNDAY) {\n\t\t\t\t\t\tday += 1;\n\t\t\t\t\t}\n\n\t\t\t\t\ttcal.set(Calendar.SECOND, sec);\n\t\t\t\t\ttcal.set(Calendar.MINUTE, min);\n\t\t\t\t\ttcal.set(Calendar.HOUR_OF_DAY, hr);\n\t\t\t\t\ttcal.set(Calendar.DAY_OF_MONTH, day);\n\t\t\t\t\ttcal.set(Calendar.MONTH, mon - 1);\n\t\t\t\t\tfinal Date nTime = tcal.getTime();\n\t\t\t\t\tif (nTime.before(afterTime)) {\n\t\t\t\t\t\tday = daysOfMonth.first();\n\t\t\t\t\t\tmon++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (st != null && st.size() != 0) {\n\t\t\t\t\tt = day;\n\t\t\t\t\tday = st.first();\n\t\t\t\t\t// make sure we don't over-run a short month, such as february\n\t\t\t\t\tfinal int lastDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR));\n\t\t\t\t\tif (day > lastDay) {\n\t\t\t\t\t\tday = daysOfMonth.first();\n\t\t\t\t\t\tmon++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tday = daysOfMonth.first();\n\t\t\t\t\tmon++;\n\t\t\t\t}\n\n\t\t\t\tif (day != t || mon != tmon) {\n\t\t\t\t\tcl.set(Calendar.SECOND, 0);\n\t\t\t\t\tcl.set(Calendar.MINUTE, 0);\n\t\t\t\t\tcl.set(Calendar.HOUR_OF_DAY, 0);\n\t\t\t\t\tcl.set(Calendar.DAY_OF_MONTH, day);\n\t\t\t\t\tcl.set(Calendar.MONTH, mon - 1);\n\t\t\t\t\t// '- 1' because calendar is 0-based for this field, and we\n\t\t\t\t\t// are 1-based\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (dayOfWSpec && !dayOfMSpec) { // get day by day of week rule\n\t\t\t\tif (lastdayOfWeek) { // are we looking for the last XXX day of\n\t\t\t\t\t// the month?\n\t\t\t\t\tfinal int dow = daysOfWeek.first(); // desired\n\t\t\t\t\t// d-o-w\n\t\t\t\t\tfinal int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w\n\t\t\t\t\tint daysToAdd = 0;\n\t\t\t\t\tif (cDow < dow) {\n\t\t\t\t\t\tdaysToAdd = dow - cDow;\n\t\t\t\t\t}\n\t\t\t\t\tif (cDow > dow) {\n\t\t\t\t\t\tdaysToAdd = dow + (7 - cDow);\n\t\t\t\t\t}\n\n\t\t\t\t\tfinal int lDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR));\n\n\t\t\t\t\tif (day + daysToAdd > lDay) { // did we already miss the\n\t\t\t\t\t\t// last one?\n\t\t\t\t\t\tcl.set(Calendar.SECOND, 0);\n\t\t\t\t\t\tcl.set(Calendar.MINUTE, 0);\n\t\t\t\t\t\tcl.set(Calendar.HOUR_OF_DAY, 0);\n\t\t\t\t\t\tcl.set(Calendar.DAY_OF_MONTH, 1);\n\t\t\t\t\t\tcl.set(Calendar.MONTH, mon);\n\t\t\t\t\t\t// no '- 1' here because we are promoting the month\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// find date of last occurrence of this day in this month...\n\t\t\t\t\twhile ((day + daysToAdd + 7) <= lDay) {\n\t\t\t\t\t\tdaysToAdd += 7;\n\t\t\t\t\t}\n\t\t\t\t\tday += daysToAdd;\n\t\t\t\t\tif (daysToAdd > 0) {\n\t\t\t\t\t\tcl.set(Calendar.SECOND, 0);\n\t\t\t\t\t\tcl.set(Calendar.MINUTE, 0);\n\t\t\t\t\t\tcl.set(Calendar.HOUR_OF_DAY, 0);\n\t\t\t\t\t\tcl.set(Calendar.DAY_OF_MONTH, day);\n\t\t\t\t\t\tcl.set(Calendar.MONTH, mon - 1);\n\t\t\t\t\t\t// '- 1' here because we are not promoting the month\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (nthdayOfWeek != 0) {\n\t\t\t\t\t// are we looking for the Nth XXX day in the month?\n\t\t\t\t\tfinal int dow = daysOfWeek.first(); // desired\n\t\t\t\t\t// d-o-w\n\t\t\t\t\tfinal int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w\n\t\t\t\t\tint daysToAdd = 0;\n\t\t\t\t\tif (cDow < dow) {\n\t\t\t\t\t\tdaysToAdd = dow - cDow;\n\t\t\t\t\t}\n\t\t\t\t\telse if (cDow > dow) {\n\t\t\t\t\t\tdaysToAdd = dow + (7 - cDow);\n\t\t\t\t\t}\n\n\t\t\t\t\tboolean dayShifted = false;\n\t\t\t\t\tif (daysToAdd > 0) {\n\t\t\t\t\t\tdayShifted = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tday += daysToAdd;\n\t\t\t\t\tint weekOfMonth = day / 7;\n\t\t\t\t\tif (day % 7 > 0) {\n\t\t\t\t\t\tweekOfMonth++;\n\t\t\t\t\t}\n\n\t\t\t\t\tdaysToAdd = (nthdayOfWeek - weekOfMonth) * 7;\n\t\t\t\t\tday += daysToAdd;\n\t\t\t\t\tif (daysToAdd < 0\n\t\t\t\t\t\t\t|| day > getLastDayOfMonth(mon, cl\n\t\t\t\t\t\t\t.get(Calendar.YEAR))) {\n\t\t\t\t\t\tcl.set(Calendar.SECOND, 0);\n\t\t\t\t\t\tcl.set(Calendar.MINUTE, 0);\n\t\t\t\t\t\tcl.set(Calendar.HOUR_OF_DAY, 0);\n\t\t\t\t\t\tcl.set(Calendar.DAY_OF_MONTH, 1);\n\t\t\t\t\t\tcl.set(Calendar.MONTH, mon);\n\t\t\t\t\t\t// no '- 1' here because we are promoting the month\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\telse if (daysToAdd > 0 || dayShifted) {\n\t\t\t\t\t\tcl.set(Calendar.SECOND, 0);\n\t\t\t\t\t\tcl.set(Calendar.MINUTE, 0);\n\t\t\t\t\t\tcl.set(Calendar.HOUR_OF_DAY, 0);\n\t\t\t\t\t\tcl.set(Calendar.DAY_OF_MONTH, day);\n\t\t\t\t\t\tcl.set(Calendar.MONTH, mon - 1);\n\t\t\t\t\t\t// '- 1' here because we are NOT promoting the month\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tfinal int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w\n\t\t\t\t\tint dow = daysOfWeek.first(); // desired\n\t\t\t\t\t// d-o-w\n\t\t\t\t\tst = daysOfWeek.tailSet(cDow);\n\t\t\t\t\tif (st != null && st.size() > 0) {\n\t\t\t\t\t\tdow = st.first();\n\t\t\t\t\t}\n\n\t\t\t\t\tint daysToAdd = 0;\n\t\t\t\t\tif (cDow < dow) {\n\t\t\t\t\t\tdaysToAdd = dow - cDow;\n\t\t\t\t\t}\n\t\t\t\t\tif (cDow > dow) {\n\t\t\t\t\t\tdaysToAdd = dow + (7 - cDow);\n\t\t\t\t\t}\n\n\t\t\t\t\tfinal int lDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR));\n\n\t\t\t\t\tif (day + daysToAdd > lDay) { // will we pass the end of\n\t\t\t\t\t\t// the month?\n\t\t\t\t\t\tcl.set(Calendar.SECOND, 0);\n\t\t\t\t\t\tcl.set(Calendar.MINUTE, 0);\n\t\t\t\t\t\tcl.set(Calendar.HOUR_OF_DAY, 0);\n\t\t\t\t\t\tcl.set(Calendar.DAY_OF_MONTH, 1);\n\t\t\t\t\t\tcl.set(Calendar.MONTH, mon);\n\t\t\t\t\t\t// no '- 1' here because we are promoting the month\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\telse if (daysToAdd > 0) { // are we switching days?\n\t\t\t\t\t\tcl.set(Calendar.SECOND, 0);\n\t\t\t\t\t\tcl.set(Calendar.MINUTE, 0);\n\t\t\t\t\t\tcl.set(Calendar.HOUR_OF_DAY, 0);\n\t\t\t\t\t\tcl.set(Calendar.DAY_OF_MONTH, day + daysToAdd);\n\t\t\t\t\t\tcl.set(Calendar.MONTH, mon - 1);\n\t\t\t\t\t\t// '- 1' because calendar is 0-based for this field,\n\t\t\t\t\t\t// and we are 1-based\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse { // dayOfWSpec && !dayOfMSpec\n\t\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\t\"Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.\");\n\t\t\t}\n\t\t\tcl.set(Calendar.DAY_OF_MONTH, day);\n\n\t\t\tmon = cl.get(Calendar.MONTH) + 1;\n\t\t\t// '+ 1' because calendar is 0-based for this field, and we are\n\t\t\t// 1-based\n\t\t\tint year = cl.get(Calendar.YEAR);\n\t\t\tt = -1;\n\n\t\t\t// test for expressions that never generate a valid fire date,\n\t\t\t// but keep looping...\n\t\t\tif (year > MAX_YEAR) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// get month...................................................\n\t\t\tst = months.tailSet(mon);\n\t\t\tif (st != null && st.size() != 0) {\n\t\t\t\tt = mon;\n\t\t\t\tmon = st.first();\n\t\t\t}\n\t\t\telse {\n\t\t\t\tmon = months.first();\n\t\t\t\tyear++;\n\t\t\t}\n\t\t\tif (mon != t) {\n\t\t\t\tcl.set(Calendar.SECOND, 0);\n\t\t\t\tcl.set(Calendar.MINUTE, 0);\n\t\t\t\tcl.set(Calendar.HOUR_OF_DAY, 0);\n\t\t\t\tcl.set(Calendar.DAY_OF_MONTH, 1);\n\t\t\t\tcl.set(Calendar.MONTH, mon - 1);\n\t\t\t\t// '- 1' because calendar is 0-based for this field, and we are\n\t\t\t\t// 1-based\n\t\t\t\tcl.set(Calendar.YEAR, year);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcl.set(Calendar.MONTH, mon - 1);\n\t\t\t// '- 1' because calendar is 0-based for this field, and we are\n\t\t\t// 1-based\n\n\t\t\tyear = cl.get(Calendar.YEAR);\n\t\t\tt = -1;\n\n\t\t\t// get year...................................................\n\t\t\tst = years.tailSet(year);\n\t\t\tif (st != null && st.size() != 0) {\n\t\t\t\tt = year;\n\t\t\t\tyear = st.first();\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn null; // ran out of years...\n\t\t\t}\n\n\t\t\tif (year != t) {\n\t\t\t\tcl.set(Calendar.SECOND, 0);\n\t\t\t\tcl.set(Calendar.MINUTE, 0);\n\t\t\t\tcl.set(Calendar.HOUR_OF_DAY, 0);\n\t\t\t\tcl.set(Calendar.DAY_OF_MONTH, 1);\n\t\t\t\tcl.set(Calendar.MONTH, 0);\n\t\t\t\t// '- 1' because calendar is 0-based for this field, and we are\n\t\t\t\t// 1-based\n\t\t\t\tcl.set(Calendar.YEAR, year);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcl.set(Calendar.YEAR, year);\n\n\t\t\tgotOne = true;\n\t\t} // while( !done )\n\n\t\treturn cl.getTime();\n\t}\n\n\t/**\n\t * Advance the calendar to the particular hour paying particular attention\n\t * to daylight saving problems.\n\t *\n\t * @param cal  the calendar to operate on\n\t * @param hour the hour to set\n\t */\n\tprotected void setCalendarHour(final Calendar cal, final int hour) {\n\t\tcal.set(Calendar.HOUR_OF_DAY, hour);\n\t\tif (cal.get(Calendar.HOUR_OF_DAY) != hour && hour != 24) {\n\t\t\tcal.set(Calendar.HOUR_OF_DAY, hour + 1);\n\t\t}\n\t}\n\n\tprotected Date getTimeBefore(final Date targetDate) {\n\t\tfinal Calendar cl = Calendar.getInstance(getTimeZone());\n\n\t\t// CronTrigger does not deal with milliseconds, so truncate target\n\t\tcl.setTime(targetDate);\n\t\tcl.set(Calendar.MILLISECOND, 0);\n\t\tfinal Date targetDateNoMs = cl.getTime();\n\n\t\t// to match this\n\t\tDate start = targetDateNoMs;\n\t\tfinal long minIncrement = findMinIncrement();\n\t\tDate prevFireTime;\n\t\tdo {\n\t\t\tfinal Date prevCheckDate = new Date(start.getTime() - minIncrement);\n\t\t\tprevFireTime = getTimeAfter(prevCheckDate);\n\t\t\tif (prevFireTime == null || prevFireTime.before(MIN_DATE)) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tstart = prevCheckDate;\n\t\t} while (prevFireTime.compareTo(targetDateNoMs) >= 0);\n\t\treturn prevFireTime;\n\t}\n\n\tpublic Date getPrevFireTime(final Date targetDate) {\n\t\treturn getTimeBefore(targetDate);\n\t}\n\n\tprivate long findMinIncrement() {\n\t\tif (seconds.size() != 1) {\n\t\t\treturn minInSet(seconds) * 1000;\n\t\t}\n\t\telse if (seconds.first() == ALL_SPEC_INT) {\n\t\t\treturn 1000;\n\t\t}\n\t\tif (minutes.size() != 1) {\n\t\t\treturn minInSet(minutes) * 60000;\n\t\t}\n\t\telse if (minutes.first() == ALL_SPEC_INT) {\n\t\t\treturn 60000;\n\t\t}\n\t\tif (hours.size() != 1) {\n\t\t\treturn minInSet(hours) * 3600000;\n\t\t}\n\t\telse if (hours.first() == ALL_SPEC_INT) {\n\t\t\treturn 3600000;\n\t\t}\n\t\treturn 86400000;\n\t}\n\n\tprivate int minInSet(final TreeSet<Integer> set) {\n\t\tint previous = 0;\n\t\tint min = Integer.MAX_VALUE;\n\t\tboolean first = true;\n\t\tfor (final int value : set) {\n\t\t\tif (first) {\n\t\t\t\tprevious = value;\n\t\t\t\tfirst = false;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfinal int diff = value - previous;\n\t\t\t\tif (diff < min) {\n\t\t\t\t\tmin = diff;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn min;\n\t}\n\n\tprotected boolean isLeapYear(final int year) {\n\t\treturn ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0));\n\t}\n\n\tprotected int getLastDayOfMonth(final int monthNum, final int year) {\n\t\tswitch (monthNum) {\n\t\t\tcase 1:\n\t\t\t\treturn 31;\n\t\t\tcase 2:\n\t\t\t\treturn (isLeapYear(year)) ? 29 : 28;\n\t\t\tcase 3:\n\t\t\t\treturn 31;\n\t\t\tcase 4:\n\t\t\t\treturn 30;\n\t\t\tcase 5:\n\t\t\t\treturn 31;\n\t\t\tcase 6:\n\t\t\t\treturn 30;\n\t\t\tcase 7:\n\t\t\t\treturn 31;\n\t\t\tcase 8:\n\t\t\t\treturn 31;\n\t\t\tcase 9:\n\t\t\t\treturn 30;\n\t\t\tcase 10:\n\t\t\t\treturn 31;\n\t\t\tcase 11:\n\t\t\t\treturn 30;\n\t\t\tcase 12:\n\t\t\t\treturn 31;\n\t\t\tdefault:\n\t\t\t\tthrow new IllegalArgumentException(\"Illegal month number: \"\n\t\t\t\t\t\t+ monthNum);\n\t\t}\n\t}\n\n\tprivate static final class ValueSet {\n\n\t\t/**\n\t\t * value.\n\t\t */\n\t\tpublic int value;\n\n\t\t/**\n\t\t * position in the expression.\n\t\t */\n\t\tpublic int pos;\n\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/java/com/alibaba/cloud/scheduling/shedlock/ShedLockAutoConfigure.java",
    "content": "/*\n * Copyright 2024-present the original author or 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\npackage com.alibaba.cloud.scheduling.shedlock;\n\nimport javax.sql.DataSource;\n\nimport com.alibaba.cloud.scheduling.SchedulingConstants;\nimport net.javacrumbs.shedlock.core.LockProvider;\nimport net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;\nimport net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;\n\nimport org.springframework.boot.autoconfigure.AutoConfigureAfter;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.io.ClassPathResource;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.jdbc.datasource.init.DataSourceInitializer;\nimport org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;\n\n/**\n * @author yaohui\n **/\n@Configuration(proxyBeanMethods = false)\n@AutoConfigureAfter(DataSourceAutoConfiguration.class)\n@EnableSchedulerLock(defaultLockAtMostFor = \"1m\")\n@ConditionalOnBean(DataSource.class)\n@ConditionalOnProperty(name = SchedulingConstants.SCHEDULING_CONFIG_DISTRIBUTED_MODE_KEY, havingValue = \"shedlock\")\npublic class ShedLockAutoConfigure {\n\n\tprivate static final String SCHEDULED_LOCK_SCHEMA_PATH = \"shedlock/schema/schema-mysql.sql\";\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\tpublic LockProvider lockProvider(DataSource dataSource) {\n\t\treturn new JdbcTemplateLockProvider(JdbcTemplateLockProvider.Configuration.builder()\n\t\t\t\t.withJdbcTemplate(new JdbcTemplate(dataSource))\n\t\t\t\t.usingDbTime()\n\t\t\t\t.build());\n\t}\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\tpublic DataSourceInitializer shedLockDataSourceInitializer(DataSource dataSource) {\n\t\tResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();\n\t\tresourceDatabasePopulator.addScript(new ClassPathResource(SCHEDULED_LOCK_SCHEMA_PATH));\n\t\tDataSourceInitializer dataSourceInitializer = new DataSourceInitializer();\n\t\tdataSourceInitializer.setDataSource(dataSource);\n\t\tdataSourceInitializer.setDatabasePopulator(resourceDatabasePopulator);\n\t\treturn dataSourceInitializer;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports",
    "content": "com.alibaba.cloud.scheduling.schedulerx.SchedulerxAutoConfigure\ncom.alibaba.cloud.scheduling.shedlock.ShedLockAutoConfigure\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/resources/META-INF/spring.factories",
    "content": "org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\\ncom.alibaba.cloud.scheduling.schedulerx.SchedulerxAutoConfigure,\\\ncom.alibaba.cloud.scheduling.shedlock.ShedLockAutoConfigure\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/resources/shedlock/schema/schema-mysql.sql",
    "content": "CREATE TABLE IF NOT EXISTS shedlock(name VARCHAR(64) NOT NULL, lock_until TIMESTAMP(3) NOT NULL,\n    locked_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), locked_by VARCHAR(255) NOT NULL, PRIMARY KEY (name));\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/test/java/com/alibaba/cloud/scheduling/schedulerx/util/CronExpressionTest.java",
    "content": "/*\n * Copyright 2024-present the original author or 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\npackage com.alibaba.cloud.scheduling.schedulerx.util;\n\nimport java.text.ParseException;\nimport java.util.Date;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author yaohui\n */\nclass CronExpressionTest {\n\n\t@Test\n\tvoid isValidExpression() {\n\t\tassertThat(CronExpression.isValidExpression(\"0 0 0 * * ?\")).isEqualTo(true);\n\t\tassertThat(CronExpression.isValidExpression(\"0 */5 * * * ?\")).isEqualTo(true);\n\t\tassertThat(CronExpression.isValidExpression(\"0 0 8 1 JAN ?\")).isEqualTo(true);\n\t\tassertThat(CronExpression.isValidExpression(\"0 0 8 ? 10 THU\")).isEqualTo(true);\n\t\tassertThat(CronExpression.isValidExpression(\"0 0 8 ? 10 THU-SAT\")).isEqualTo(true);\n\t\tassertThat(CronExpression.isValidExpression(\"0 0 8 ? 10 FRI#1\")).isEqualTo(true);\n\t\tassertThat(CronExpression.isValidExpression(\"0 0 8 ? 10 FRI#5\")).isEqualTo(true);\n\t\t// false\n\t\tassertThat(CronExpression.isValidExpression(\"0 0 8 1 JAW ?\")).isEqualTo(false);\n\t\tassertThat(CronExpression.isValidExpression(\"0 0 8 ? 10 THP-SAT\")).isEqualTo(false);\n\t\tassertThat(CronExpression.isValidExpression(\"0 0 8 ? 10 FRI#0\")).isEqualTo(false);\n\t\tassertThat(CronExpression.isValidExpression(\"0 0 8 ? 10 FRI#6\")).isEqualTo(false);\n\t}\n\n\t@Test\n\tvoid getTimeAfter() throws ParseException {\n\t\tCronExpression cronExpression = new CronExpression(\"0 0 8 1 JAN ?\");\n\t\tDate nextDate = cronExpression.getTimeAfter(new Date());\n\t\tSystem.out.println(nextDate);\n\t\tassertThat(nextDate).isNotNull();\n\n\t\tcronExpression = new CronExpression(\"0 */5 * * * ?\");\n\t\tnextDate = cronExpression.getTimeAfter(new Date());\n\t\tSystem.out.println(nextDate);\n\t\tassertThat(nextDate).isNotNull();\n\t}\n\n\t@Test\n\tvoid getTimeBefore() throws ParseException {\n\t\tCronExpression cronExpression = new CronExpression(\"0 0 8 1 JAN ?\");\n\t\tDate beforeDate = cronExpression.getTimeBefore(new Date());\n\t\tSystem.out.println(beforeDate);\n\t\tassertThat(beforeDate).isNotNull();\n\n\t\tcronExpression = new CronExpression(\"0 */5 * * * ?\");\n\t\tbeforeDate = cronExpression.getTimeBefore(new Date());\n\t\tSystem.out.println(beforeDate);\n\t\tassertThat(beforeDate).isNotNull();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-starters</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>\n    <name>Spring Cloud Starter Alibaba Seata</name>\n\n    <dependencies>\n\n        <!--spring boot-->\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-webclient</artifactId>\n\t\t</dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-aspectj</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-configuration-processor</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-webflux</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.seata</groupId>\n            <artifactId>seata-spring-boot-starter</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-openfeign</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-commons</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-loadbalancer</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n    </dependencies>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignBuilderBeanPostProcessor.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.seata.feign;\n\nimport feign.Feign;\nimport feign.Retryer;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.config.BeanPostProcessor;\n\n/**\n * @author wang.liang\n * @since 2.2.5\n */\npublic class SeataFeignBuilderBeanPostProcessor implements BeanPostProcessor {\n\n\tprivate static final Logger LOGGER = LoggerFactory.getLogger(SeataFeignBuilderBeanPostProcessor.class);\n\n\t@Override\n\tpublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {\n\t\tif (bean instanceof Feign.Builder) {\n\t\t\t((Feign.Builder) bean).retryer(Retryer.NEVER_RETRY);\n\t\t\tLOGGER.info(\"change the retryer of the bean '{}' to 'Retryer.NEVER_RETRY'\", beanName);\n\t\t}\n\t\treturn bean;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignClientAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.seata.feign;\n\nimport feign.Client;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author xiaojing\n * @author wang.liang\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnClass(Client.class)\npublic class SeataFeignClientAutoConfiguration {\n\n\t@Bean\n\tpublic static SeataFeignBuilderBeanPostProcessor seataFeignBuilderBeanPostProcessor() {\n\t\treturn new SeataFeignBuilderBeanPostProcessor();\n\t}\n\n\t@Bean\n\tpublic SeataFeignRequestInterceptor seataFeignRequestInterceptor() {\n\t\treturn new SeataFeignRequestInterceptor();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignRequestInterceptor.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.seata.feign;\n\nimport feign.RequestInterceptor;\nimport feign.RequestTemplate;\nimport org.apache.seata.core.context.RootContext;\n\nimport org.springframework.util.StringUtils;\n\n/**\n * @author wang.liang\n */\npublic class SeataFeignRequestInterceptor implements RequestInterceptor {\n\n\t@Override\n\tpublic void apply(RequestTemplate template) {\n\t\tString xid = RootContext.getXID();\n\t\tif (!StringUtils.hasLength(xid)) {\n\t\t\treturn;\n\t\t}\n\n\t\ttemplate.header(RootContext.KEY_XID, xid);\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/rest/SeataRestTemplateAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.seata.rest;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.client.RestClient;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author xiaojing\n * @author ChangJin Wei (魏昌进)\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnClass({RestClient.class, RestTemplate.class})\npublic class SeataRestTemplateAutoConfiguration {\n\n\t@Bean\n\tpublic SeataRestTemplateInterceptor seataRestTemplateInterceptor() {\n\t\treturn new SeataRestTemplateInterceptor();\n\t}\n\n\t@Bean\n\tpublic SeataRestTemplateInterceptorAfterPropertiesSet seataRestTemplateInterceptorConfiguration() {\n\t\treturn new SeataRestTemplateInterceptorAfterPropertiesSet();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/rest/SeataRestTemplateInterceptor.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.seata.rest;\n\nimport java.io.IOException;\n\nimport org.apache.seata.core.context.RootContext;\n\nimport org.springframework.http.HttpRequest;\nimport org.springframework.http.client.ClientHttpRequestExecution;\nimport org.springframework.http.client.ClientHttpRequestInterceptor;\nimport org.springframework.http.client.ClientHttpResponse;\nimport org.springframework.http.client.support.HttpRequestWrapper;\nimport org.springframework.util.StringUtils;\n\n/**\n * @author xiaojing\n */\npublic class SeataRestTemplateInterceptor implements ClientHttpRequestInterceptor {\n\n\t@Override\n\tpublic ClientHttpResponse intercept(HttpRequest httpRequest, byte[] bytes,\n\t\t\tClientHttpRequestExecution clientHttpRequestExecution) throws IOException {\n\t\tHttpRequestWrapper requestWrapper = new HttpRequestWrapper(httpRequest);\n\n\t\tString xid = RootContext.getXID();\n\n\t\tif (StringUtils.hasLength(xid)) {\n\t\t\trequestWrapper.getHeaders().add(RootContext.KEY_XID, xid);\n\t\t}\n\t\treturn clientHttpRequestExecution.execute(requestWrapper, bytes);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/rest/SeataRestTemplateInterceptorAfterPropertiesSet.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.seata.rest;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\n\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.client.ClientHttpRequestInterceptor;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author ZhangZhi\n */\npublic class SeataRestTemplateInterceptorAfterPropertiesSet implements InitializingBean {\n\n\t@Autowired(required = false)\n\tprivate Collection<RestTemplate> restTemplates;\n\n\t@Autowired\n\tprivate SeataRestTemplateInterceptor seataRestTemplateInterceptor;\n\n\t@Override\n\tpublic void afterPropertiesSet() {\n\t\tif (this.restTemplates != null) {\n\t\t\tfor (RestTemplate restTemplate : restTemplates) {\n\t\t\t\tList<ClientHttpRequestInterceptor> interceptors = new ArrayList<>(\n\t\t\t\t\t\trestTemplate.getInterceptors());\n\t\t\t\tinterceptors.add(this.seataRestTemplateInterceptor);\n\t\t\t\trestTemplate.setInterceptors(interceptors);\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/web/SeataHandlerInterceptor.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.seata.web;\n\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpServletResponse;\nimport org.apache.seata.common.util.StringUtils;\nimport org.apache.seata.core.context.RootContext;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.web.servlet.HandlerInterceptor;\n\n/**\n * @author xiaojing\n *\n * Seata HandlerInterceptor, Convert Seata information into\n * @see org.apache.seata.core.context.RootContext from http request's header in\n * {@link org.springframework.web.servlet.HandlerInterceptor#preHandle(HttpServletRequest, HttpServletResponse, Object)},\n * And clean up Seata information after servlet method invocation in\n * {@link org.springframework.web.servlet.HandlerInterceptor#afterCompletion(HttpServletRequest, HttpServletResponse, Object, Exception)}\n */\npublic class SeataHandlerInterceptor implements HandlerInterceptor {\n\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(SeataHandlerInterceptor.class);\n\n\t@Override\n\tpublic boolean preHandle(HttpServletRequest request, HttpServletResponse response,\n\t\t\tObject handler) {\n\t\tString xid = RootContext.getXID();\n\t\tString rpcXid = request.getHeader(RootContext.KEY_XID);\n\t\tif (log.isDebugEnabled()) {\n\t\t\tlog.debug(\"xid in RootContext {} xid in RpcContext {}\", xid, rpcXid);\n\t\t}\n\n\t\tif (StringUtils.isBlank(xid) && rpcXid != null) {\n\t\t\tRootContext.bind(rpcXid);\n\t\t\tif (log.isDebugEnabled()) {\n\t\t\t\tlog.debug(\"bind {} to RootContext\", rpcXid);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void afterCompletion(HttpServletRequest request, HttpServletResponse response,\n\t\t\tObject handler, Exception e) {\n\t\tif (StringUtils.isNotBlank(RootContext.getXID())) {\n\t\t\tString rpcXid = request.getHeader(RootContext.KEY_XID);\n\n\t\t\tif (StringUtils.isEmpty(rpcXid)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tString unbindXid = RootContext.unbind();\n\t\t\tif (log.isDebugEnabled()) {\n\t\t\t\tlog.debug(\"unbind {} from RootContext\", unbindXid);\n\t\t\t}\n\t\t\tif (!rpcXid.equalsIgnoreCase(unbindXid)) {\n\t\t\t\tlog.warn(\"xid in change during RPC from {} to {}\", rpcXid, unbindXid);\n\t\t\t\tif (unbindXid != null) {\n\t\t\t\t\tRootContext.bind(unbindXid);\n\t\t\t\t\tlog.warn(\"bind {} back to RootContext\", unbindXid);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/web/SeataHandlerInterceptorConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.seata.web;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;\nimport org.springframework.web.servlet.config.annotation.InterceptorRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurer;\n\n/**\n * @author xiaojing\n * @author ChangJin Wei (魏昌进)\n */\n@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)\npublic class SeataHandlerInterceptorConfiguration implements WebMvcConfigurer {\n\n\t@Override\n\tpublic void addInterceptors(InterceptorRegistry registry) {\n\t\tregistry.addInterceptor(new SeataHandlerInterceptor()).addPathPatterns(\"/**\");\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/webclient/SeataWebClientAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.seata.webclient;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.webclient.WebClientCustomizer;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.reactive.function.client.WebClient;\n\n/**\n * @author ChangJin Wei (魏昌进)\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnClass(WebClient.class)\npublic class SeataWebClientAutoConfiguration {\n\n\t@Bean\n\tpublic SeataWebClientFilter seataWebClientFilter() {\n\t\treturn new SeataWebClientFilter();\n\t}\n\n\t@Bean\n\tpublic WebClientCustomizer seataWebClientCustomizer(SeataWebClientFilter filter) {\n\t\treturn new SeataWebClientBuilderCustomizer(filter);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/webclient/SeataWebClientBuilderCustomizer.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.seata.webclient;\n\nimport org.springframework.boot.webclient.WebClientCustomizer;\nimport org.springframework.web.reactive.function.client.WebClient;\n\n/**\n * @author ChangJin Wei (魏昌进)\n */\npublic class SeataWebClientBuilderCustomizer implements WebClientCustomizer {\n\tprivate final SeataWebClientFilter filter;\n\n\tpublic SeataWebClientBuilderCustomizer(SeataWebClientFilter filter) {\n\t\tthis.filter = filter;\n\t}\n\n\t@Override\n\tpublic void customize(WebClient.Builder builder) {\n\t\tbuilder.filter(filter);\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/webclient/SeataWebClientFilter.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.seata.webclient;\n\nimport org.apache.seata.core.context.RootContext;\nimport reactor.core.publisher.Mono;\n\nimport org.springframework.util.StringUtils;\nimport org.springframework.web.reactive.function.client.ClientRequest;\nimport org.springframework.web.reactive.function.client.ClientResponse;\nimport org.springframework.web.reactive.function.client.ExchangeFilterFunction;\nimport org.springframework.web.reactive.function.client.ExchangeFunction;\n\n/**\n * @author ChangJin Wei (魏昌进)\n */\npublic class SeataWebClientFilter implements ExchangeFilterFunction {\n\n\t@Override\n\tpublic Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {\n\t\tString xid = RootContext.getXID();\n\t\tif (!StringUtils.hasLength(xid)) {\n\t\t\treturn next.exchange(request);\n\t\t}\n\t\tClientRequest newReq = ClientRequest.from(request)\n\t\t\t\t.headers(h -> h.add(RootContext.KEY_XID, xid))\n\t\t\t\t.build();\n\t\treturn next.exchange(newReq);\n\t}\n\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/webflux/SeataWebFilter.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.seata.webflux;\n\nimport org.apache.seata.common.util.StringUtils;\nimport org.apache.seata.core.context.RootContext;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport reactor.core.publisher.Mono;\n\nimport org.springframework.web.server.ServerWebExchange;\nimport org.springframework.web.server.WebFilter;\nimport org.springframework.web.server.WebFilterChain;\n\n/**\n * @author ChangJin Wei (魏昌进)\n */\npublic class SeataWebFilter implements WebFilter {\n\n\tprivate static final Logger log = LoggerFactory.getLogger(SeataWebFilter.class);\n\n\t@Override\n\tpublic Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {\n\t\tString xid = RootContext.getXID();\n\t\tString rpcXid = exchange.getRequest().getHeaders().getFirst(RootContext.KEY_XID);\n\t\tif (log.isDebugEnabled()) {\n\t\t\tlog.debug(\"xid in RootContext {} xid in RpcContext {}\", xid, rpcXid);\n\t\t}\n\n\t\tif (StringUtils.isBlank(xid) && rpcXid != null) {\n\t\t\tRootContext.bind(rpcXid);\n\t\t\tif (log.isDebugEnabled()) {\n\t\t\t\tlog.debug(\"bind {} to RootContext\", rpcXid);\n\t\t\t}\n\t\t}\n\n\t\treturn chain.filter(exchange)\n\t\t\t\t.doFinally(sig -> {\n\t\t\t\t\tif (StringUtils.isNotBlank(RootContext.getXID())) {\n\t\t\t\t\t\tString headerXid = exchange.getRequest().getHeaders().getFirst(RootContext.KEY_XID);\n\n\t\t\t\t\t\tif (StringUtils.isEmpty(headerXid)) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tString unbindXid = RootContext.unbind();\n\t\t\t\t\t\tif (log.isDebugEnabled()) {\n\t\t\t\t\t\t\tlog.debug(\"unbind {} from RootContext\", unbindXid);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!headerXid.equalsIgnoreCase(unbindXid)) {\n\t\t\t\t\t\t\tlog.warn(\"xid in change during RPC from {} to {}\", headerXid, unbindXid);\n\t\t\t\t\t\t\tif (unbindXid != null) {\n\t\t\t\t\t\t\t\tRootContext.bind(unbindXid);\n\t\t\t\t\t\t\t\tlog.warn(\"bind {} back to RootContext\", unbindXid);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/webflux/SeataWebfluxAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.seata.webflux;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.web.reactive.config.WebFluxConfigurer;\nimport org.springframework.web.server.WebFilter;\n\n/**\n * @author ChangJin Wei (魏昌进)\n */\n@ConditionalOnClass({WebFilter.class, WebFluxConfigurer.class})\n@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)\npublic class SeataWebfluxAutoConfiguration {\n\n\t@Bean\n\tpublic WebFilter seataWebFilter() {\n\t\treturn new SeataWebFilter();\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/resources/META-INF/native-image/com.alibaba.cloud/spring-cloud-starter-alibaba-seata/native-image.properties",
    "content": "Args = --initialize-at-build-time=ch.qos.logback.classic.Logger \\\n--initialize-at-build-time=ch.qos.logback.core.status.InfoStatus \\\n--initialize-at-build-time=ch.qos.logback.core.status.StatusBase \\\n--initialize-at-build-time=org.slf4j.LoggerFactory \\\n--initialize-at-build-time=ch.qos.logback.core.CoreConstants \\\n--initialize-at-build-time=org.slf4j.MDC \\\n--initialize-at-build-time=ch.qos.logback.classic.Level \\\n--initialize-at-build-time=ch.qos.logback.core.util.Loader \\\n--initialize-at-build-time=ch.qos.logback.core.util.StatusPrinter \\\n--initialize-at-run-time=io.netty.channel.epoll.Epoll \\\n--initialize-at-run-time=io.netty.channel.epoll.Native \\\n--initialize-at-run-time=io.netty.channel.epoll.EpollEventLoop \\\n--initialize-at-run-time=io.netty.channel.epoll.EpollEventArray \\\n--initialize-at-run-time=io.netty.channel.DefaultFileRegion \\\n--initialize-at-run-time=io.netty.channel.kqueue.KQueueEventArray \\\n--initialize-at-run-time=io.netty.channel.kqueue.KQueueEventLoop \\\n--initialize-at-run-time=io.netty.channel.kqueue.Native \\\n--initialize-at-run-time=io.netty.channel.unix.Errors \\\n--initialize-at-run-time=io.netty.channel.unix.IovArray \\\n--initialize-at-run-time=io.netty.channel.unix.Limits \\\n--initialize-at-run-time=io.netty.util.internal.logging.Log4JLogger \\\n--initialize-at-run-time=io.netty.channel.unix.Socket \\\n--initialize-at-run-time=io.netty.channel.ChannelHandlerMask\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/resources/META-INF/native-image/proxy-config.json",
    "content": "[\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.config.ConfigurationCache\"\n    },\n    \"interfaces\": [\n      \"org.apache.config.Configuration\"\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.spring.boot.autoconfigure.provider.SpringBootConfigurationProvider\"\n    },\n    \"interfaces\": [\n      \"org.apache.config.Configuration\"\n    ]\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/resources/META-INF/native-image/reflect-config.json",
    "content": "[\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.config.ConfigurationCache\"\n    },\n    \"name\": \"org.apache.config.Configuration\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.config.ConfigurationCache$$Lambda$494/0x00000008010e8000\"\n    },\n    \"name\": \"org.apache.config.Configuration\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.core.event.GuavaEventBus\"\n    },\n    \"name\": \"org.apache.config.ConfigurationChangeListener\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.config.ConfigurationFactory\"\n    },\n    \"name\": \"org.apache.config.apollo.ApolloConfigurationProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.config.ConfigurationFactory\"\n    },\n    \"name\": \"org.apache.config.consul.ConsulConfigurationProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.config.ConfigurationFactory\"\n    },\n    \"name\": \"org.apache.config.custom.CustomConfigurationProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.config.ConfigurationFactory\"\n    },\n    \"name\": \"org.apache.config.etcd3.EtcdConfigurationProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.common.loader.EnhancedServiceLoader$InnerEnhancedServiceLoader\"\n    },\n    \"name\": \"org.apache.config.file.SimpleFileConfig\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.common.loader.EnhancedServiceLoader$InnerEnhancedServiceLoader\"\n    },\n    \"name\": \"org.apache.config.file.YamlFileConfig\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.config.ConfigurationFactory\"\n    },\n    \"name\": \"org.apache.config.nacos.NacosConfigurationProvider\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.config.processor.ConfigProcessor\"\n    },\n    \"name\": \"org.apache.config.processor.ProcessorProperties\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.config.processor.ConfigProcessor\"\n    },\n    \"name\": \"org.apache.config.processor.ProcessorYaml\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.config.ConfigurationFactory\"\n    },\n    \"name\": \"org.apache.config.springcloud.SpringCloudConfigurationProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.config.ConfigurationFactory\"\n    },\n    \"name\": \"org.apache.config.zk.ZookeeperConfigurationProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.core.rpc.netty.TmNettyRemotingClient\"\n    },\n    \"name\": \"org.apache.core.auth.DefaultAuthSigner\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.core.context.ContextCoreLoader$ContextCoreHolder\"\n    },\n    \"name\": \"org.apache.core.context.FastThreadLocalContextCore\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.core.context.ContextCoreLoader$ContextCoreHolder\"\n    },\n    \"name\": \"org.apache.core.context.ThreadLocalContextCore\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.core.rpc.netty.AbstractNettyRemoting\"\n    },\n    \"name\": \"org.apache.core.rpc.hook.StatusRpcHook\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.core.rpc.netty.NettyClientBootstrap\"\n    },\n    \"name\": \"org.apache.core.rpc.netty.AbstractNettyRemotingClient$ClientHandler\",\n    \"methods\": [\n      {\n        \"name\": \"channelInactive\",\n        \"parameterTypes\": [\n          \"io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"channelRead\",\n        \"parameterTypes\": [\n          \"io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\"\n        ]\n      },\n      {\n        \"name\": \"channelWritabilityChanged\",\n        \"parameterTypes\": [\n          \"io.netty.channel.ChannelHandlerContext\"\n        ]\n      },\n      {\n        \"name\": \"close\",\n        \"parameterTypes\": [\n          \"io.netty.channel.ChannelHandlerContext\",\n          \"io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"exceptionCaught\",\n        \"parameterTypes\": [\n          \"io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Throwable\"\n        ]\n      },\n      {\n        \"name\": \"userEventTriggered\",\n        \"parameterTypes\": [\n          \"io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.core.rpc.netty.NettyClientBootstrap\"\n    },\n    \"name\": \"org.apache.core.rpc.netty.NettyClientBootstrap$1\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.core.rpc.netty.NettyClientBootstrap$1\"\n    },\n    \"name\": \"org.apache.core.rpc.netty.v1.ProtocolV1Decoder\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.core.rpc.netty.NettyClientBootstrap$1\"\n    },\n    \"name\": \"org.apache.core.rpc.netty.v1.ProtocolV1Encoder\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.discovery.registry.RegistryFactory\"\n    },\n    \"name\": \"org.apache.discovery.registry.FileRegistryProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.discovery.registry.RegistryFactory\"\n    },\n    \"name\": \"org.apache.discovery.registry.consul.ConsulRegistryProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.discovery.registry.RegistryFactory\"\n    },\n    \"name\": \"org.apache.discovery.registry.custom.CustomRegistryProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.discovery.registry.RegistryFactory\"\n    },\n    \"name\": \"org.apache.discovery.registry.etcd3.EtcdRegistryProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.discovery.registry.RegistryFactory\"\n    },\n    \"name\": \"org.apache.discovery.registry.eureka.EurekaRegistryProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.discovery.registry.RegistryFactory\"\n    },\n    \"name\": \"org.apache.discovery.registry.nacos.NacosRegistryProvider\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.discovery.registry.RegistryFactory\"\n    },\n    \"name\": \"org.apache.discovery.registry.redis.RedisRegistryProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.discovery.registry.RegistryFactory\"\n    },\n    \"name\": \"org.apache.discovery.registry.sofa.SofaRegistryProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.discovery.registry.RegistryFactory\"\n    },\n    \"name\": \"org.apache.discovery.registry.zk.ZookeeperRegistryProvider\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.spring.annotation.GlobalTransactionScanner\"\n    },\n    \"name\": \"org.apache.integration.http.JakartaSeataWebMvcConfigurer\",\n    \"queryAllPublicMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.rm.DefaultRMHandler\"\n    },\n    \"name\": \"org.apache.rm.RMHandlerAT\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.rm.DefaultRMHandler\"\n    },\n    \"name\": \"org.apache.rm.RMHandlerXA\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.rm.DefaultResourceManager\"\n    },\n    \"name\": \"org.apache.rm.datasource.DataSourceManager\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.rm.DefaultResourceManager\"\n    },\n    \"name\": \"org.apache.rm.datasource.xa.ResourceManagerXA\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.rm.DefaultRMHandler\"\n    },\n    \"name\": \"org.apache.rm.tcc.RMHandlerTCC\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.rm.DefaultResourceManager\"\n    },\n    \"name\": \"org.apache.rm.tcc.TCCResourceManager\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.rm.tcc.remoting.parser.DefaultRemotingParser\"\n    },\n    \"name\": \"org.apache.rm.tcc.remoting.parser.DubboRemotingParser\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.rm.tcc.remoting.parser.DefaultRemotingParser\"\n    },\n    \"name\": \"org.apache.rm.tcc.remoting.parser.HSFRemotingParser\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.rm.tcc.remoting.parser.DefaultRemotingParser\"\n    },\n    \"name\": \"org.apache.rm.tcc.remoting.parser.LocalTCCRemotingParser\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.rm.tcc.remoting.parser.DefaultRemotingParser\"\n    },\n    \"name\": \"org.apache.rm.tcc.remoting.parser.SofaRpcRemotingParser\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.rm.DefaultRMHandler\"\n    },\n    \"name\": \"org.apache.saga.rm.RMHandlerSaga\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.rm.DefaultResourceManager\"\n    },\n    \"name\": \"org.apache.saga.rm.SagaResourceManager\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.core.serializer.SerializerServiceLoader\"\n    },\n    \"name\": \"org.apache.serializer.fst.FstSerializer\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.core.serializer.SerializerServiceLoader\"\n    },\n    \"name\": \"org.apache.serializer.hessian.HessianSerializer\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.core.serializer.SerializerServiceLoader\"\n    },\n    \"name\": \"org.apache.serializer.kryo.KryoSerializer\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.core.serializer.SerializerServiceLoader\"\n    },\n    \"name\": \"org.apache.serializer.seata.SeataSerializer\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.core.event.GuavaEventBus\"\n    },\n    \"name\": \"org.apache.spring.annotation.GlobalTransactionalInterceptor\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.core.event.GuavaEventBus\"\n    },\n    \"name\": \"org.apache.spring.annotation.SeataInterceptor\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.spring.boot.autoconfigure.SeataAutoConfiguration\"\n    },\n    \"name\": \"org.apache.spring.annotation.scannercheckers.ConfigBeansScannerChecker\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.spring.boot.autoconfigure.SeataAutoConfiguration\"\n    },\n    \"name\": \"org.apache.spring.annotation.scannercheckers.PackageScannerChecker\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.spring.boot.autoconfigure.SeataAutoConfiguration\"\n    },\n    \"name\": \"org.apache.spring.annotation.scannercheckers.ScopeBeansScannerChecker\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.config.ConfigurationFactory\"\n    },\n    \"name\": \"org.apache.spring.boot.autoconfigure.provider.SpringBootConfigurationProvider\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.tm.TransactionManagerHolder$SingletonHolder\"\n    },\n    \"name\": \"org.apache.tm.DefaultTransactionManager\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/resources/META-INF/native-image/resource-config.json",
    "content": "{\n  \"resources\": {\n    \"includes\": [\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.config.nacos.NacosConfiguration\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.api.config.filter.IConfigFilter\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.config.nacos.NacosConfiguration\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.api.remote.Payload\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.config.nacos.NacosConfiguration\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.plugin.auth.spi.client.AbstractClientAuthService\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.config.nacos.NacosConfiguration\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.shaded.io.grpc.LoadBalancerProvider\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.config.nacos.NacosConfiguration\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.shaded.io.grpc.ManagedChannelProvider\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.config.nacos.NacosConfiguration\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.nacos.shaded.io.grpc.NameResolverProvider\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.config.ConfigurationFactory\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/org.apache.config.ConfigurationProvider\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.config.ConfigurationFactory\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/org.apache.config.ExtConfigurationProvider\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.common.loader.EnhancedServiceLoader$InnerEnhancedServiceLoader\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/org.apache.config.file.FileConfig\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.config.processor.ConfigProcessor\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/org.apache.config.processor.Processor\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.core.rpc.netty.TmNettyRemotingClient\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/org.apache.core.auth.AuthSigner\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.core.context.ContextCoreLoader$ContextCoreHolder\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/org.apache.core.context.ContextCore\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.rm.DefaultResourceManager\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/org.apache.core.model.ResourceManager\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.tm.TransactionManagerHolder$SingletonHolder\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/org.apache.core.model.TransactionManager\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.core.rpc.netty.AbstractNettyRemoting\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/org.apache.core.rpc.hook.RpcHook\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.core.serializer.SerializerServiceLoader\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/org.apache.core.serializer.Serializer\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.discovery.registry.RegistryFactory\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/org.apache.discovery.registry.RegistryProvider\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.rm.DefaultRMHandler\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/org.apache.rm.AbstractRMHandler\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.rm.tcc.remoting.parser.DefaultRemotingParser\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/org.apache.rm.tcc.remoting.RemotingParser\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.spring.boot.autoconfigure.SeataAutoConfiguration\"\n        },\n        \"pattern\": \"\\\\QMETA-INF/services/org.apache.spring.annotation.ScannerChecker\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.config.FileConfiguration\"\n        },\n        \"pattern\": \"\\\\Q\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.config.nacos.NacosConfiguration\"\n        },\n        \"pattern\": \"\\\\Qnacos-version.txt\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.spring.annotation.GlobalTransactionalInterceptor$2\"\n        },\n        \"pattern\": \"\\\\Qorg/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfiguration$BlockingRetryConfiguration.class\\\\E\"\n      },\n      {\n        \"condition\": {\n          \"typeReachable\": \"org.apache.spring.annotation.GlobalTransactionalInterceptor$2\"\n        },\n        \"pattern\": \"\\\\Qorg/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfiguration$BlockingSupportConfiguration.class\\\\E\"\n      }\n    ]\n  },\n  \"bundles\": []\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports",
    "content": "com.alibaba.cloud.seata.rest.SeataRestTemplateAutoConfiguration\ncom.alibaba.cloud.seata.web.SeataHandlerInterceptorConfiguration\ncom.alibaba.cloud.seata.feign.SeataFeignClientAutoConfiguration\ncom.alibaba.cloud.seata.webclient.SeataWebClientAutoConfiguration\ncom.alibaba.cloud.seata.webflux.SeataWebfluxAutoConfiguration\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-starters</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>\n    <name>Spring Cloud Starter Alibaba Sentinel</name>\n\n    <dependencies>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-health</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <!--spring boot-->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-aspectj</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-actuator</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-actuator-autoconfigure</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-configuration-processor</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-autoconfigure</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-webflux</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-openfeign</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-commons</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-loadbalancer</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-transport-simple-http</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-annotation-aspectj</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-circuitbreaker-sentinel</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-spring-webflux-adapter</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-spring-webmvc-v6x-adapter</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-parameter-flow-control</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-api-gateway-adapter-common</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-cluster-server-default</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.csp</groupId>\n            <artifactId>sentinel-cluster-client-default</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>tools.jackson.dataformat</groupId>\n            <artifactId>jackson-dataformat-xml</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>junit</groupId>\n            <artifactId>junit</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n    </dependencies>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelConstants.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel;\n\n/**\n * @author fangjian\n */\npublic final class SentinelConstants {\n\n\t/**\n\t * Prefix of {@link SentinelProperties}.\n\t */\n\tpublic static final String PROPERTY_PREFIX = \"spring.cloud.sentinel\";\n\n\t/**\n\t * Block page key.\n\t */\n\tpublic static final String BLOCK_PAGE_URL_CONF_KEY = \"csp.sentinel.web.servlet.block.page\";\n\n\t/**\n\t * Block type.\n\t */\n\tpublic static final String BLOCK_TYPE = \"block\";\n\n\t/**\n\t * Fallback type.\n\t */\n\tpublic static final String FALLBACK_TYPE = \"fallback\";\n\n\t/**\n\t * UrlCleaner type.\n\t */\n\tpublic static final String URLCLEANER_TYPE = \"urlCleaner\";\n\n\t/**\n\t * The cold factor.\n\t */\n\tpublic static final String COLD_FACTOR = \"3\";\n\n\t/**\n\t * The charset.\n\t */\n\tpublic static final String CHARSET = \"UTF-8\";\n\n\t/**\n\t * The Sentinel api port.\n\t */\n\tpublic static final String API_PORT = \"8719\";\n\n\tprivate SentinelConstants() {\n\t\tthrow new AssertionError(\"Must not instantiate constant utility class\");\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.TreeMap;\n\nimport com.alibaba.cloud.sentinel.datasource.config.DataSourcePropertiesConfiguration;\nimport com.alibaba.csp.sentinel.config.SentinelConfig;\nimport com.alibaba.csp.sentinel.log.LogBase;\nimport com.alibaba.csp.sentinel.transport.config.TransportConfig;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.boot.context.properties.DeprecatedConfigurationProperty;\nimport org.springframework.core.Ordered;\nimport org.springframework.util.StringUtils;\n\n/**\n * {@link ConfigurationProperties} for Sentinel.\n *\n * @author xiaojing\n * @author hengyunabc\n * @author jiashuai.xie\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@ConfigurationProperties(prefix = SentinelConstants.PROPERTY_PREFIX)\npublic class SentinelProperties {\n\n\t/**\n\t * Earlier initialize heart-beat when the spring container starts when the transport\n\t * dependency is on classpath, the configuration is effective.\n\t */\n\tprivate boolean eager = false;\n\n\t/**\n\t * Enable sentinel auto configure, the default value is true.\n\t */\n\tprivate boolean enabled = true;\n\n\t/**\n\t * The process page when the flow control is triggered.\n\t */\n\tprivate String blockPage;\n\n\t/**\n\t * Configurations about datasource, like 'nacos', 'apollo', 'file', 'zookeeper'.\n\t */\n\tprivate Map<String, DataSourcePropertiesConfiguration> datasource = new TreeMap<>(\n\t\t\tString.CASE_INSENSITIVE_ORDER);\n\n\t/**\n\t * Transport configuration about dashboard and client.\n\t */\n\tprivate Transport transport = new Transport();\n\n\t/**\n\t * Metric configuration about resource.\n\t */\n\tprivate Metric metric = new Metric();\n\n\t/**\n\t * Web servlet configuration when the application is web, the configuration is\n\t * effective.\n\t */\n\tprivate Servlet servlet = new Servlet();\n\n\t/**\n\t * Sentinel interceptor when the application is web, the configuration is effective.\n\t */\n\tprivate Filter filter = new Filter();\n\n\t/**\n\t * Sentinel Flow configuration.\n\t */\n\tprivate Flow flow = new Flow();\n\n\t/**\n\t * Sentinel log configuration {@link LogBase}.\n\t */\n\tprivate Log log = new Log();\n\n\t/**\n\t * Add HTTP method prefix for Sentinel Resource.\n\t */\n\tprivate Boolean httpMethodSpecify = false;\n\n\t/**\n\t * Specify whether unify web context(i.e. use the default context name), and is true\n\t * by default.\n\t */\n\tprivate Boolean webContextUnify = true;\n\n\tpublic Boolean getWebContextUnify() {\n\t\treturn webContextUnify;\n\t}\n\n\tpublic void setWebContextUnify(Boolean webContextUnify) {\n\t\tthis.webContextUnify = webContextUnify;\n\t}\n\n\tpublic boolean isEager() {\n\t\treturn eager;\n\t}\n\n\tpublic void setEager(boolean eager) {\n\t\tthis.eager = eager;\n\t}\n\n\tpublic Flow getFlow() {\n\t\treturn flow;\n\t}\n\n\tpublic void setFlow(Flow flow) {\n\t\tthis.flow = flow;\n\t}\n\n\tpublic Transport getTransport() {\n\t\treturn transport;\n\t}\n\n\tpublic void setTransport(Transport transport) {\n\t\tthis.transport = transport;\n\t}\n\n\tpublic Metric getMetric() {\n\t\treturn metric;\n\t}\n\n\tpublic void setMetric(Metric metric) {\n\t\tthis.metric = metric;\n\t}\n\n\tpublic Servlet getServlet() {\n\t\treturn servlet;\n\t}\n\n\tpublic void setServlet(Servlet servlet) {\n\t\tthis.servlet = servlet;\n\t}\n\n\tpublic boolean isEnabled() {\n\t\treturn enabled;\n\t}\n\n\tpublic void setEnabled(boolean enabled) {\n\t\tthis.enabled = enabled;\n\t}\n\n\tpublic Filter getFilter() {\n\t\treturn filter;\n\t}\n\n\tpublic void setFilter(Filter filter) {\n\t\tthis.filter = filter;\n\t}\n\n\tpublic Map<String, DataSourcePropertiesConfiguration> getDatasource() {\n\t\treturn datasource;\n\t}\n\n\tpublic void setDatasource(Map<String, DataSourcePropertiesConfiguration> datasource) {\n\t\tthis.datasource = datasource;\n\t}\n\n\tpublic Log getLog() {\n\t\treturn log;\n\t}\n\n\tpublic void setLog(Log log) {\n\t\tthis.log = log;\n\t}\n\n\tpublic Boolean getHttpMethodSpecify() {\n\t\treturn httpMethodSpecify;\n\t}\n\n\tpublic void setHttpMethodSpecify(Boolean httpMethodSpecify) {\n\t\tthis.httpMethodSpecify = httpMethodSpecify;\n\t}\n\n\tpublic String getBlockPage() {\n\t\tif (StringUtils.hasText(this.blockPage)) {\n\t\t\treturn this.blockPage;\n\t\t}\n\t\treturn this.servlet.getBlockPage();\n\t}\n\n\tpublic void setBlockPage(String blockPage) {\n\t\tthis.blockPage = blockPage;\n\t}\n\n\tpublic static class Flow {\n\n\t\t/**\n\t\t * The cold factor {@link SentinelConfig#COLD_FACTOR}.\n\t\t */\n\t\tprivate String coldFactor = SentinelConstants.COLD_FACTOR;\n\n\t\tpublic String getColdFactor() {\n\t\t\treturn coldFactor;\n\t\t}\n\n\t\tpublic void setColdFactor(String coldFactor) {\n\t\t\tthis.coldFactor = coldFactor;\n\t\t}\n\n\t}\n\n\tpublic static class Servlet {\n\n\t\t/**\n\t\t * The process page when the flow control is triggered.\n\t\t */\n\t\tprivate String blockPage;\n\n\t\t@Deprecated\n\t\t@DeprecatedConfigurationProperty(\n\t\t\t\treason = \"replaced to SentinelProperties#blockPage.\",\n\t\t\t\treplacement = SentinelConstants.PROPERTY_PREFIX + \".block-page\")\n\t\tpublic String getBlockPage() {\n\t\t\treturn blockPage;\n\t\t}\n\n\t\t@Deprecated\n\t\tpublic void setBlockPage(String blockPage) {\n\t\t\tthis.blockPage = blockPage;\n\t\t}\n\n\t}\n\n\tpublic static class Metric {\n\n\t\t/**\n\t\t * The metric file size {@link SentinelConfig#SINGLE_METRIC_FILE_SIZE}.\n\t\t */\n\t\tprivate String fileSingleSize;\n\n\t\t/**\n\t\t * The total metric file count {@link SentinelConfig#TOTAL_METRIC_FILE_COUNT}.\n\t\t */\n\t\tprivate String fileTotalCount;\n\n\t\t/**\n\t\t * Charset when sentinel write or search metric file.\n\t\t * {@link SentinelConfig#CHARSET}\n\t\t */\n\t\tprivate String charset = SentinelConstants.CHARSET;\n\n\t\tpublic String getFileSingleSize() {\n\t\t\treturn fileSingleSize;\n\t\t}\n\n\t\tpublic void setFileSingleSize(String fileSingleSize) {\n\t\t\tthis.fileSingleSize = fileSingleSize;\n\t\t}\n\n\t\tpublic String getFileTotalCount() {\n\t\t\treturn fileTotalCount;\n\t\t}\n\n\t\tpublic void setFileTotalCount(String fileTotalCount) {\n\t\t\tthis.fileTotalCount = fileTotalCount;\n\t\t}\n\n\t\tpublic String getCharset() {\n\t\t\treturn charset;\n\t\t}\n\n\t\tpublic void setCharset(String charset) {\n\t\t\tthis.charset = charset;\n\t\t}\n\n\t}\n\n\tpublic static class Transport {\n\n\t\t/**\n\t\t * Sentinel api port, default value is 8719 {@link TransportConfig#SERVER_PORT}.\n\t\t */\n\t\tprivate String port = SentinelConstants.API_PORT;\n\n\t\t/**\n\t\t * Sentinel dashboard address, won't try to connect dashboard when address is\n\t\t * empty {@link TransportConfig#CONSOLE_SERVER}.\n\t\t */\n\t\tprivate String dashboard = \"\";\n\n\t\t/**\n\t\t * Send heartbeat interval millisecond\n\t\t * {@link TransportConfig#HEARTBEAT_INTERVAL_MS}.\n\t\t */\n\t\tprivate String heartbeatIntervalMs;\n\n\t\t/**\n\t\t * Get heartbeat client local ip. If the client ip not configured, it will be the\n\t\t * address of local host.\n\t\t */\n\t\tprivate String clientIp;\n\n\t\tpublic String getHeartbeatIntervalMs() {\n\t\t\treturn heartbeatIntervalMs;\n\t\t}\n\n\t\tpublic void setHeartbeatIntervalMs(String heartbeatIntervalMs) {\n\t\t\tthis.heartbeatIntervalMs = heartbeatIntervalMs;\n\t\t}\n\n\t\tpublic String getPort() {\n\t\t\treturn port;\n\t\t}\n\n\t\tpublic void setPort(String port) {\n\t\t\tthis.port = port;\n\t\t}\n\n\t\tpublic String getDashboard() {\n\t\t\treturn dashboard;\n\t\t}\n\n\t\tpublic void setDashboard(String dashboard) {\n\t\t\tthis.dashboard = dashboard;\n\t\t}\n\n\t\tpublic String getClientIp() {\n\t\t\treturn clientIp;\n\t\t}\n\n\t\tpublic void setClientIp(String clientIp) {\n\t\t\tthis.clientIp = clientIp;\n\t\t}\n\n\t}\n\n\tpublic static class Filter {\n\n\t\t/**\n\t\t * SentinelWebInterceptor order, will be register to InterceptorRegistry.\n\t\t */\n\t\tprivate int order = Ordered.HIGHEST_PRECEDENCE;\n\n\t\t/**\n\t\t * URL pattern for SentinelWebInterceptor, default is /**.\n\t\t */\n\t\tprivate List<String> urlPatterns = Arrays.asList(\"/**\");\n\n\t\t/**\n\t\t * Enable to instance\n\t\t * {@link com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor}.\n\t\t */\n\t\tprivate boolean enabled = true;\n\n\t\tpublic int getOrder() {\n\t\t\treturn this.order;\n\t\t}\n\n\t\tpublic void setOrder(int order) {\n\t\t\tthis.order = order;\n\t\t}\n\n\t\tpublic List<String> getUrlPatterns() {\n\t\t\treturn urlPatterns;\n\t\t}\n\n\t\tpublic void setUrlPatterns(List<String> urlPatterns) {\n\t\t\tthis.urlPatterns = urlPatterns;\n\t\t}\n\n\t\tpublic boolean isEnabled() {\n\t\t\treturn enabled;\n\t\t}\n\n\t\tpublic void setEnabled(boolean enabled) {\n\t\t\tthis.enabled = enabled;\n\t\t}\n\n\t}\n\n\tpublic static class Log {\n\n\t\t/**\n\t\t * Sentinel log base dir.\n\t\t */\n\t\tprivate String dir;\n\n\t\t/**\n\t\t * Distinguish the log file by pid number.\n\t\t */\n\t\tprivate boolean switchPid = false;\n\n\t\tpublic String getDir() {\n\t\t\treturn dir;\n\t\t}\n\n\t\tpublic void setDir(String dir) {\n\t\t\tthis.dir = dir;\n\t\t}\n\n\t\tpublic boolean isSwitchPid() {\n\t\t\treturn switchPid;\n\t\t}\n\n\t\tpublic void setSwitchPid(boolean switchPid) {\n\t\t\tthis.switchPid = switchPid;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel;\n\nimport java.util.Optional;\n\nimport com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.SentinelWebInterceptor;\nimport com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.BlockExceptionHandler;\nimport com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.DefaultBlockExceptionHandler;\nimport com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.RequestOriginParser;\nimport com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.config.SentinelWebMvcConfig;\nimport com.alibaba.csp.sentinel.adapter.web.common.UrlCleaner;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.util.StringUtils;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurer;\n\n/**\n * @author xiaojing\n * @author yuhuangbin\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnWebApplication(type = Type.SERVLET)\n@ConditionalOnProperty(name = \"spring.cloud.sentinel.enabled\", matchIfMissing = true)\n@ConditionalOnClass(SentinelWebInterceptor.class)\n@EnableConfigurationProperties(SentinelProperties.class)\npublic class SentinelWebAutoConfiguration implements WebMvcConfigurer {\n\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(SentinelWebAutoConfiguration.class);\n\n\t@Autowired\n\tprivate SentinelProperties properties;\n\n\t@Autowired\n\tprivate Optional<UrlCleaner> urlCleanerOptional;\n\n\t@Autowired\n\tprivate Optional<BlockExceptionHandler> blockExceptionHandlerOptional;\n\n\t@Autowired\n\tprivate Optional<RequestOriginParser> requestOriginParserOptional;\n\n\t@Bean\n\t@ConditionalOnProperty(name = \"spring.cloud.sentinel.filter.enabled\",\n\t\t\tmatchIfMissing = true)\n\tpublic SentinelWebInterceptor sentinelWebInterceptor(\n\t\t\tSentinelWebMvcConfig sentinelWebMvcConfig) {\n\t\treturn new SentinelWebInterceptor(sentinelWebMvcConfig);\n\t}\n\n\t@Bean\n\t@ConditionalOnProperty(name = \"spring.cloud.sentinel.filter.enabled\",\n\t\t\tmatchIfMissing = true)\n\tpublic SentinelWebMvcConfig sentinelWebMvcConfig() {\n\t\tSentinelWebMvcConfig sentinelWebMvcConfig = new SentinelWebMvcConfig();\n\t\tsentinelWebMvcConfig.setHttpMethodSpecify(properties.getHttpMethodSpecify());\n\t\tsentinelWebMvcConfig.setWebContextUnify(properties.getWebContextUnify());\n\n\t\tif (blockExceptionHandlerOptional.isPresent()) {\n\t\t\tblockExceptionHandlerOptional\n\t\t\t\t\t.ifPresent(sentinelWebMvcConfig::setBlockExceptionHandler);\n\t\t}\n\t\telse {\n\t\t\tif (StringUtils.hasText(properties.getBlockPage())) {\n\t\t\t\tsentinelWebMvcConfig.setBlockExceptionHandler(\n\t\t\t\t\t\t(request, response, resourceName, e) ->\n\t\t\t\t\t\t\t\tresponse.sendRedirect(properties.getBlockPage())\n\t\t\t\t);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tsentinelWebMvcConfig\n\t\t\t\t\t\t.setBlockExceptionHandler(new DefaultBlockExceptionHandler());\n\t\t\t}\n\t\t}\n\n\t\turlCleanerOptional.ifPresent(sentinelWebMvcConfig::setUrlCleaner);\n\t\trequestOriginParserOptional.ifPresent(sentinelWebMvcConfig::setOriginParser);\n\t\treturn sentinelWebMvcConfig;\n\t}\n\n\t@Bean\n\t@ConditionalOnProperty(name = \"spring.cloud.sentinel.filter.enabled\",\n\t\t\tmatchIfMissing = true)\n\tpublic SentinelWebMvcConfigurer sentinelWebMvcConfigurer() {\n\t\treturn new SentinelWebMvcConfigurer();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebFluxAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Optional;\n\nimport com.alibaba.csp.sentinel.adapter.reactor.SentinelReactorTransformer;\nimport com.alibaba.csp.sentinel.adapter.spring.webflux.SentinelWebFluxFilter;\nimport com.alibaba.csp.sentinel.adapter.spring.webflux.callback.BlockRequestHandler;\nimport com.alibaba.csp.sentinel.adapter.spring.webflux.callback.WebFluxCallbackManager;\nimport com.alibaba.csp.sentinel.adapter.spring.webflux.exception.SentinelBlockExceptionHandler;\nimport jakarta.annotation.PostConstruct;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.ObjectProvider;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.http.codec.ServerCodecConfigurer;\nimport org.springframework.web.reactive.result.view.ViewResolver;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnWebApplication(type = Type.REACTIVE)\n@ConditionalOnClass(SentinelReactorTransformer.class)\n@ConditionalOnProperty(name = \"spring.cloud.sentinel.enabled\", matchIfMissing = true)\n@EnableConfigurationProperties(SentinelProperties.class)\npublic class SentinelWebFluxAutoConfiguration {\n\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(SentinelWebFluxAutoConfiguration.class);\n\n\tprivate final List<ViewResolver> viewResolvers;\n\n\tprivate final ServerCodecConfigurer serverCodecConfigurer;\n\n\t@Autowired\n\tprivate Optional<BlockRequestHandler> blockRequestHandler;\n\n\tpublic SentinelWebFluxAutoConfiguration(\n\t\t\tObjectProvider<List<ViewResolver>> viewResolvers,\n\t\t\tServerCodecConfigurer serverCodecConfigurer) {\n\t\tthis.viewResolvers = viewResolvers.getIfAvailable(Collections::emptyList);\n\t\tthis.serverCodecConfigurer = serverCodecConfigurer;\n\t}\n\n\t@PostConstruct\n\tpublic void init() {\n\t\tblockRequestHandler.ifPresent(WebFluxCallbackManager::setBlockHandler);\n\t}\n\n\t@Bean\n\t@Order(-2)\n\t@ConditionalOnProperty(name = \"spring.cloud.sentinel.filter.enabled\",\n\t\t\tmatchIfMissing = true)\n\tpublic SentinelBlockExceptionHandler sentinelBlockExceptionHandler() {\n\t\treturn new SentinelBlockExceptionHandler(viewResolvers, serverCodecConfigurer);\n\t}\n\n\t@Bean\n\t@Order(-1)\n\t@ConditionalOnProperty(name = \"spring.cloud.sentinel.filter.enabled\",\n\t\t\tmatchIfMissing = true)\n\tpublic SentinelWebFluxFilter sentinelWebFluxFilter() {\n\t\tlog.info(\"[Sentinel Starter] register Sentinel SentinelWebFluxFilter\");\n\t\treturn new SentinelWebFluxFilter();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebMvcConfigurer.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel;\n\nimport java.util.Optional;\n\nimport com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.SentinelWebInterceptor;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.servlet.config.annotation.InterceptorRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurer;\n\n/**\n * @author chao.wu\n */\npublic class SentinelWebMvcConfigurer implements WebMvcConfigurer {\n\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(SentinelWebMvcConfigurer.class);\n\n\t@Autowired\n\tprivate SentinelProperties sentinelProperties;\n\n\t@Autowired\n\tprivate Optional<SentinelWebInterceptor> sentinelWebInterceptorOptional;\n\n\t@Override\n\tpublic void addInterceptors(InterceptorRegistry registry) {\n\t\tif (!sentinelWebInterceptorOptional.isPresent()) {\n\t\t\treturn;\n\t\t}\n\t\tSentinelProperties.Filter filterConfig = sentinelProperties.getFilter();\n\t\tregistry.addInterceptor(sentinelWebInterceptorOptional.get())\n\t\t\t\t.order(filterConfig.getOrder())\n\t\t\t\t.addPathPatterns(filterConfig.getUrlPatterns());\n\t\tlog.info(\n\t\t\t\t\"[Sentinel Starter] register SentinelWebInterceptor with urlPatterns: {}.\",\n\t\t\t\tfilterConfig.getUrlPatterns());\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/annotation/SentinelRestTemplate.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.annotation;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * @author fangjian\n */\n@Target({ ElementType.METHOD })\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\npublic @interface SentinelRestTemplate {\n\n\tString blockHandler() default \"\";\n\n\tClass<?> blockHandlerClass() default void.class;\n\n\tString fallback() default \"\";\n\n\tClass<?> fallbackClass() default void.class;\n\n\tString urlCleaner() default \"\";\n\n\tClass<?> urlCleanerClass() default void.class;\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/aot/hint/SentinelProtectInterceptorHints.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.aot.hint;\n\nimport java.lang.reflect.Constructor;\n\nimport com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;\nimport com.alibaba.cloud.sentinel.custom.SentinelProtectInterceptor;\n\nimport org.springframework.aot.hint.ExecutableMode;\nimport org.springframework.aot.hint.RuntimeHints;\nimport org.springframework.aot.hint.RuntimeHintsRegistrar;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author ruansheneg\n */\npublic class SentinelProtectInterceptorHints implements RuntimeHintsRegistrar {\n\t@Override\n\tpublic void registerHints(RuntimeHints hints, ClassLoader classLoader) {\n\t\tConstructor<SentinelProtectInterceptor> constructor;\n\t\ttry {\n\t\t\tconstructor = SentinelProtectInterceptor.class.getConstructor(SentinelRestTemplate.class, RestTemplate.class);\n\t\t}\n\t\tcatch (NoSuchMethodException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\thints.reflection().registerConstructor(constructor, ExecutableMode.INVOKE);\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/BlockClassRegistry.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.custom;\n\nimport java.lang.reflect.Method;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport com.alibaba.csp.sentinel.util.StringUtil;\n\n/**\n * @author fangjian\n */\nfinal class BlockClassRegistry {\n\n\tprivate BlockClassRegistry() {\n\n\t}\n\n\tprivate static final Map<String, Method> FALLBACK_MAP = new ConcurrentHashMap<>();\n\n\tprivate static final Map<String, Method> BLOCK_HANDLER_MAP = new ConcurrentHashMap<>();\n\n\tprivate static final Map<String, Method> URL_CLEANER_MAP = new ConcurrentHashMap<>();\n\n\tstatic Method lookupFallback(Class<?> clazz, String name) {\n\t\treturn FALLBACK_MAP.get(getKey(clazz, name));\n\t}\n\n\tstatic Method lookupBlockHandler(Class<?> clazz, String name) {\n\t\treturn BLOCK_HANDLER_MAP.get(getKey(clazz, name));\n\t}\n\n\tstatic Method lookupUrlCleaner(Class<?> clazz, String name) {\n\t\treturn URL_CLEANER_MAP.get(getKey(clazz, name));\n\t}\n\n\tstatic void updateFallbackFor(Class<?> clazz, String name, Method method) {\n\t\tif (clazz == null || StringUtil.isBlank(name)) {\n\t\t\tthrow new IllegalArgumentException(\"Bad argument\");\n\t\t}\n\t\tFALLBACK_MAP.put(getKey(clazz, name), method);\n\t}\n\n\tstatic void updateBlockHandlerFor(Class<?> clazz, String name, Method method) {\n\t\tif (clazz == null || StringUtil.isBlank(name)) {\n\t\t\tthrow new IllegalArgumentException(\"Bad argument\");\n\t\t}\n\t\tBLOCK_HANDLER_MAP.put(getKey(clazz, name), method);\n\t}\n\n\tstatic void updateUrlCleanerFor(Class<?> clazz, String name, Method method) {\n\t\tif (clazz == null || StringUtil.isBlank(name)) {\n\t\t\tthrow new IllegalArgumentException(\"Bad argument\");\n\t\t}\n\t\tURL_CLEANER_MAP.put(getKey(clazz, name), method);\n\t}\n\n\tprivate static String getKey(Class<?> clazz, String name) {\n\t\treturn String.format(\"%s:%s\", clazz.getCanonicalName(), name);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.custom;\n\n\nimport com.alibaba.cloud.sentinel.SentinelProperties;\nimport com.alibaba.cloud.sentinel.datasource.converter.JsonConverter;\nimport com.alibaba.cloud.sentinel.datasource.converter.XmlConverter;\nimport com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;\nimport com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;\nimport com.alibaba.csp.sentinel.slots.system.SystemRule;\nimport tools.jackson.databind.DeserializationFeature;\nimport tools.jackson.databind.ObjectMapper;\nimport tools.jackson.databind.json.JsonMapper;\nimport tools.jackson.dataformat.xml.XmlMapper;\n\nimport org.springframework.beans.factory.support.DefaultListableBeanFactory;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.env.Environment;\n\n/**\n * @author xiaojing\n * @author jiashuai.xie\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n * @author freeman\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnProperty(name = \"spring.cloud.sentinel.enabled\", matchIfMissing = true)\n@EnableConfigurationProperties(SentinelProperties.class)\npublic class SentinelAutoConfiguration {\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\tpublic SentinelResourceAspect sentinelResourceAspect() {\n\t\treturn new SentinelResourceAspect();\n\t}\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\t@ConditionalOnClass(name = \"org.springframework.web.client.RestTemplate\")\n\t@ConditionalOnProperty(name = \"resttemplate.sentinel.enabled\", havingValue = \"true\",\n\t\t\tmatchIfMissing = true)\n\tpublic static SentinelBeanPostProcessor sentinelBeanPostProcessor(\n\t\t\tApplicationContext applicationContext) {\n\t\treturn new SentinelBeanPostProcessor(applicationContext);\n\t}\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\tpublic SentinelDataSourceHandler sentinelDataSourceHandler(\n\t\t\tDefaultListableBeanFactory beanFactory, SentinelProperties sentinelProperties,\n\t\t\tEnvironment env) {\n\t\treturn new SentinelDataSourceHandler(beanFactory, sentinelProperties, env);\n\t}\n\n\t@ConditionalOnClass(ObjectMapper.class)\n\t@Configuration(proxyBeanMethods = false)\n\tprotected static class SentinelConverterConfiguration {\n\n\t\t@Configuration(proxyBeanMethods = false)\n\t\tprotected static class SentinelJsonConfiguration {\n\n\t\t\tprivate final ObjectMapper objectMapper;\n\n\t\t\tpublic SentinelJsonConfiguration() {\n\t\t\t\tthis.objectMapper = JsonMapper.builder()\n\t\t\t\t\t\t.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)\n\t\t\t\t\t\t.build();\n\t\t\t}\n\n\t\t\t@Bean(\"sentinel-json-flow-converter\")\n\t\t\tpublic JsonConverter jsonFlowConverter() {\n\t\t\t\treturn new JsonConverter(objectMapper, FlowRule.class);\n\t\t\t}\n\n\t\t\t@Bean(\"sentinel-json-degrade-converter\")\n\t\t\tpublic JsonConverter jsonDegradeConverter() {\n\t\t\t\treturn new JsonConverter(objectMapper, DegradeRule.class);\n\t\t\t}\n\n\t\t\t@Bean(\"sentinel-json-system-converter\")\n\t\t\tpublic JsonConverter jsonSystemConverter() {\n\t\t\t\treturn new JsonConverter(objectMapper, SystemRule.class);\n\t\t\t}\n\n\t\t\t@Bean(\"sentinel-json-authority-converter\")\n\t\t\tpublic JsonConverter jsonAuthorityConverter() {\n\t\t\t\treturn new JsonConverter(objectMapper, AuthorityRule.class);\n\t\t\t}\n\n\t\t\t@Bean(\"sentinel-json-param-flow-converter\")\n\t\t\tpublic JsonConverter jsonParamFlowConverter() {\n\t\t\t\treturn new JsonConverter(objectMapper, ParamFlowRule.class);\n\t\t\t}\n\n\t\t}\n\n\t\t@ConditionalOnClass(XmlMapper.class)\n\t\t@Configuration(proxyBeanMethods = false)\n\t\tprotected static class SentinelXmlConfiguration {\n\n\t\t\tprivate final XmlMapper xmlMapper;\n\n\t\t\tpublic SentinelXmlConfiguration() {\n\t\t\t\tthis.xmlMapper = XmlMapper.builder()\n\t\t\t\t\t\t.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)\n\t\t\t\t\t\t.build();\n\t\t\t}\n\n\t\t\t@Bean(\"sentinel-xml-flow-converter\")\n\t\t\tpublic XmlConverter xmlFlowConverter() {\n\t\t\t\treturn new XmlConverter(xmlMapper, FlowRule.class);\n\t\t\t}\n\n\t\t\t@Bean(\"sentinel-xml-degrade-converter\")\n\t\t\tpublic XmlConverter xmlDegradeConverter() {\n\t\t\t\treturn new XmlConverter(xmlMapper, DegradeRule.class);\n\t\t\t}\n\n\t\t\t@Bean(\"sentinel-xml-system-converter\")\n\t\t\tpublic XmlConverter xmlSystemConverter() {\n\t\t\t\treturn new XmlConverter(xmlMapper, SystemRule.class);\n\t\t\t}\n\n\t\t\t@Bean(\"sentinel-xml-authority-converter\")\n\t\t\tpublic XmlConverter xmlAuthorityConverter() {\n\t\t\t\treturn new XmlConverter(xmlMapper, AuthorityRule.class);\n\t\t\t}\n\n\t\t\t@Bean(\"sentinel-xml-param-flow-converter\")\n\t\t\tpublic XmlConverter xmlParamFlowConverter() {\n\t\t\t\treturn new XmlConverter(xmlMapper, ParamFlowRule.class);\n\t\t\t}\n\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelBeanPostProcessor.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.custom;\n\nimport java.lang.reflect.Method;\nimport java.util.Arrays;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport com.alibaba.cloud.sentinel.SentinelConstants;\nimport com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;\nimport com.alibaba.csp.sentinel.slots.block.BlockException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.config.BeanDefinition;\nimport org.springframework.beans.factory.support.BeanDefinitionBuilder;\nimport org.springframework.beans.factory.support.DefaultListableBeanFactory;\nimport org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;\nimport org.springframework.beans.factory.support.RootBeanDefinition;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.core.type.StandardMethodMetadata;\nimport org.springframework.http.HttpRequest;\nimport org.springframework.http.client.ClientHttpRequestExecution;\nimport org.springframework.http.client.ClientHttpResponse;\nimport org.springframework.util.ClassUtils;\nimport org.springframework.util.StringUtils;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * PostProcessor handle @SentinelRestTemplate Annotation, add interceptor for\n * RestTemplate.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n * @see SentinelRestTemplate\n * @see SentinelProtectInterceptor\n */\npublic class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProcessor {\n\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(SentinelBeanPostProcessor.class);\n\n\tprivate final ApplicationContext applicationContext;\n\n\tpublic SentinelBeanPostProcessor(ApplicationContext applicationContext) {\n\t\tthis.applicationContext = applicationContext;\n\t}\n\n\tprivate ConcurrentHashMap<String, SentinelRestTemplate> cache = new ConcurrentHashMap<>();\n\n\t@Override\n\tpublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,\n\t\t\tClass<?> beanType, String beanName) {\n\t\t// Fixes #3329: Support custom RestTemplate\n\t\tif (beanName == null || !RestTemplate.class.isAssignableFrom(beanType)) {\n\t\t\treturn;\n\t\t}\n\n\t\tSentinelRestTemplate sentinelRestTemplate = this.getSentinelRestTemplateFromBeanDefinition(beanDefinition);\n\t\tif (sentinelRestTemplate != null) {\n\t\t\t// check class and method validation\n\t\t\tcheckSentinelRestTemplate(sentinelRestTemplate, beanName);\n\t\t\tcache.put(beanName, sentinelRestTemplate);\n\t\t}\n\t}\n\n\tprivate SentinelRestTemplate getSentinelRestTemplateFromBeanDefinition(RootBeanDefinition beanDefinition) {\n\t\tSentinelRestTemplate sentinelRestTemplate = null;\n\t\tif (beanDefinition.getSource() instanceof StandardMethodMetadata sentinelSource) {\n\t\t\tsentinelRestTemplate = sentinelSource.getIntrospectedMethod().getAnnotation(SentinelRestTemplate.class);\n\t\t}\n\n\t\tif (sentinelRestTemplate == null && beanDefinition.getResolvedFactoryMethod() != null) {\n\t\t\tsentinelRestTemplate = beanDefinition.getResolvedFactoryMethod().getAnnotation(SentinelRestTemplate.class);\n\t\t}\n\n\t\treturn sentinelRestTemplate;\n\t}\n\n\tprivate void checkSentinelRestTemplate(SentinelRestTemplate sentinelRestTemplate,\n\t\t\tString beanName) {\n\t\tcheckBlock4RestTemplate(sentinelRestTemplate.blockHandlerClass(),\n\t\t\t\tsentinelRestTemplate.blockHandler(), beanName,\n\t\t\t\tSentinelConstants.BLOCK_TYPE);\n\t\tcheckBlock4RestTemplate(sentinelRestTemplate.fallbackClass(),\n\t\t\t\tsentinelRestTemplate.fallback(), beanName,\n\t\t\t\tSentinelConstants.FALLBACK_TYPE);\n\t\tcheckBlock4RestTemplate(sentinelRestTemplate.urlCleanerClass(),\n\t\t\t\tsentinelRestTemplate.urlCleaner(), beanName,\n\t\t\t\tSentinelConstants.URLCLEANER_TYPE);\n\t}\n\n\tprivate void checkBlock4RestTemplate(Class<?> blockClass, String blockMethod,\n\t\t\tString beanName, String type) {\n\t\tif (blockClass == void.class && !StringUtils.hasLength(blockMethod)) {\n\t\t\treturn;\n\t\t}\n\t\tif (blockClass != void.class && !StringUtils.hasLength(blockMethod)) {\n\t\t\tlog.error(\n\t\t\t\t\t\"{} class attribute exists but {} method attribute is not exists in bean[{}]\",\n\t\t\t\t\ttype, type, beanName);\n\t\t\tthrow new IllegalArgumentException(type + \" class attribute exists but \"\n\t\t\t\t\t+ type + \" method attribute is not exists in bean[\" + beanName + \"]\");\n\t\t}\n\t\telse if (blockClass == void.class && StringUtils.hasLength(blockMethod)) {\n\t\t\tlog.error(\n\t\t\t\t\t\"{} method attribute exists but {} class attribute is not exists in bean[{}]\",\n\t\t\t\t\ttype, type, beanName);\n\t\t\tthrow new IllegalArgumentException(type + \" method attribute exists but \"\n\t\t\t\t\t+ type + \" class attribute is not exists in bean[\" + beanName + \"]\");\n\t\t}\n\t\tClass[] args;\n\t\tif (type.equals(SentinelConstants.URLCLEANER_TYPE)) {\n\t\t\targs = new Class[] {String.class};\n\t\t}\n\t\telse {\n\t\t\targs = new Class[] {HttpRequest.class, byte[].class,\n\t\t\t\t\tClientHttpRequestExecution.class, BlockException.class};\n\t\t}\n\t\tString argsStr = Arrays.toString(\n\t\t\t\tArrays.stream(args).map(clazz -> clazz.getSimpleName()).toArray());\n\t\tMethod foundMethod = ClassUtils.getStaticMethod(blockClass, blockMethod, args);\n\t\tif (foundMethod == null) {\n\t\t\tlog.error(\n\t\t\t\t\t\"{} static method can not be found in bean[{}]. The right method signature is {}#{}{}, please check your class name, method name and arguments\",\n\t\t\t\t\ttype, beanName, blockClass.getName(), blockMethod, argsStr);\n\t\t\tthrow new IllegalArgumentException(type\n\t\t\t\t\t+ \" static method can not be found in bean[\" + beanName\n\t\t\t\t\t+ \"]. The right method signature is \" + blockClass.getName() + \"#\"\n\t\t\t\t\t+ blockMethod + argsStr\n\t\t\t\t\t+ \", please check your class name, method name and arguments\");\n\t\t}\n\n\t\tClass<?> standardReturnType;\n\t\tif (type.equals(SentinelConstants.URLCLEANER_TYPE)) {\n\t\t\tstandardReturnType = String.class;\n\t\t}\n\t\telse {\n\t\t\tstandardReturnType = ClientHttpResponse.class;\n\t\t}\n\n\t\tif (!standardReturnType.isAssignableFrom(foundMethod.getReturnType())) {\n\t\t\tlog.error(\"{} method return value in bean[{}] is not {}: {}#{}{}\", type,\n\t\t\t\t\tbeanName, standardReturnType.getName(), blockClass.getName(),\n\t\t\t\t\tblockMethod, argsStr);\n\t\t\tthrow new IllegalArgumentException(type + \" method return value in bean[\"\n\t\t\t\t\t+ beanName + \"] is not \" + standardReturnType.getName() + \": \"\n\t\t\t\t\t+ blockClass.getName() + \"#\" + blockMethod + argsStr);\n\t\t}\n\t\tif (type.equals(SentinelConstants.BLOCK_TYPE)) {\n\t\t\tBlockClassRegistry.updateBlockHandlerFor(blockClass, blockMethod,\n\t\t\t\t\tfoundMethod);\n\t\t}\n\t\telse if (type.equals(SentinelConstants.FALLBACK_TYPE)) {\n\t\t\tBlockClassRegistry.updateFallbackFor(blockClass, blockMethod, foundMethod);\n\t\t}\n\t\telse {\n\t\t\tBlockClassRegistry.updateUrlCleanerFor(blockClass, blockMethod, foundMethod);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Object postProcessAfterInitialization(Object bean, String beanName)\n\t\t\tthrows BeansException {\n\t\tif (beanName != null && cache.containsKey(beanName)) {\n\t\t\t// add interceptor for each RestTemplate with @SentinelRestTemplate annotation\n\t\t\tStringBuilder interceptorBeanNamePrefix = new StringBuilder();\n\t\t\tSentinelRestTemplate sentinelRestTemplate = cache.get(beanName);\n\t\t\tinterceptorBeanNamePrefix\n\t\t\t\t\t.append(StringUtils.uncapitalize(\n\t\t\t\t\t\t\tSentinelProtectInterceptor.class.getSimpleName()))\n\t\t\t\t\t.append(\"_\")\n\t\t\t\t\t.append(sentinelRestTemplate.blockHandlerClass().getSimpleName())\n\t\t\t\t\t.append(sentinelRestTemplate.blockHandler()).append(\"_\")\n\t\t\t\t\t.append(sentinelRestTemplate.fallbackClass().getSimpleName())\n\t\t\t\t\t.append(sentinelRestTemplate.fallback()).append(\"_\")\n\t\t\t\t\t.append(sentinelRestTemplate.urlCleanerClass().getSimpleName())\n\t\t\t\t\t.append(sentinelRestTemplate.urlCleaner());\n\t\t\tRestTemplate restTemplate = (RestTemplate) bean;\n\t\t\tString interceptorBeanName = interceptorBeanNamePrefix + \"@\"\n\t\t\t\t\t+ bean.toString();\n\t\t\tregisterBean(interceptorBeanName, sentinelRestTemplate, (RestTemplate) bean);\n\t\t\tSentinelProtectInterceptor sentinelProtectInterceptor = applicationContext\n\t\t\t\t\t.getBean(interceptorBeanName, SentinelProtectInterceptor.class);\n\t\t\trestTemplate.getInterceptors().add(0, sentinelProtectInterceptor);\n\t\t}\n\t\treturn bean;\n\t}\n\n\tprivate void registerBean(String interceptorBeanName,\n\t\t\tSentinelRestTemplate sentinelRestTemplate, RestTemplate restTemplate) {\n\t\t// register SentinelProtectInterceptor bean\n\t\tDefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext\n\t\t\t\t.getAutowireCapableBeanFactory();\n\t\tBeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder\n\t\t\t\t.genericBeanDefinition(SentinelProtectInterceptor.class);\n\t\tbeanDefinitionBuilder.addConstructorArgValue(sentinelRestTemplate);\n\t\tbeanDefinitionBuilder.addConstructorArgValue(restTemplate);\n\t\tBeanDefinition interceptorBeanDefinition = beanDefinitionBuilder\n\t\t\t\t.getRawBeanDefinition();\n\t\tbeanFactory.registerBeanDefinition(interceptorBeanName,\n\t\t\t\tinterceptorBeanDefinition);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelDataSourceHandler.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.custom;\n\nimport java.lang.reflect.Field;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\nimport com.alibaba.cloud.sentinel.SentinelProperties;\nimport com.alibaba.cloud.sentinel.datasource.config.AbstractDataSourceProperties;\nimport com.alibaba.cloud.sentinel.datasource.converter.JsonConverter;\nimport com.alibaba.cloud.sentinel.datasource.converter.XmlConverter;\nimport com.alibaba.csp.sentinel.datasource.AbstractDataSource;\nimport com.alibaba.csp.sentinel.datasource.ReadableDataSource;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.SmartInitializingSingleton;\nimport org.springframework.beans.factory.support.BeanDefinitionBuilder;\nimport org.springframework.beans.factory.support.DefaultListableBeanFactory;\nimport org.springframework.core.env.Environment;\nimport org.springframework.util.ReflectionUtils;\nimport org.springframework.util.StringUtils;\n\n/**\n * Sentinel {@link ReadableDataSource} Handler Handle the configurations of\n * 'spring.cloud.sentinel.datasource'.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n * @see SentinelProperties#datasource\n * @see JsonConverter\n * @see XmlConverter\n */\npublic class SentinelDataSourceHandler implements SmartInitializingSingleton {\n\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(SentinelDataSourceHandler.class);\n\n\tprivate final List<String> dataTypeList = Arrays.asList(\"json\", \"xml\");\n\n\tprivate final String DATA_TYPE_FIELD = \"dataType\";\n\n\tprivate final String CUSTOM_DATA_TYPE = \"custom\";\n\n\tprivate final String CONVERTER_CLASS_FIELD = \"converterClass\";\n\n\tprivate final DefaultListableBeanFactory beanFactory;\n\n\tprivate final SentinelProperties sentinelProperties;\n\n\tprivate final Environment env;\n\n\tpublic SentinelDataSourceHandler(DefaultListableBeanFactory beanFactory,\n\t\t\tSentinelProperties sentinelProperties, Environment env) {\n\t\tthis.beanFactory = beanFactory;\n\t\tthis.sentinelProperties = sentinelProperties;\n\t\tthis.env = env;\n\t}\n\n\t@Override\n\tpublic void afterSingletonsInstantiated() {\n\t\tsentinelProperties.getDatasource()\n\t\t\t\t.forEach((dataSourceName, dataSourceProperties) -> {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tList<String> validFields = dataSourceProperties.getValidField();\n\t\t\t\t\t\tif (validFields.size() != 1) {\n\t\t\t\t\t\t\tlog.error(\"[Sentinel Starter] DataSource \" + dataSourceName\n\t\t\t\t\t\t\t\t\t+ \" multi datasource active and won't loaded: \"\n\t\t\t\t\t\t\t\t\t+ dataSourceProperties.getValidField());\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tAbstractDataSourceProperties abstractDataSourceProperties = dataSourceProperties\n\t\t\t\t\t\t\t\t.getValidDataSourceProperties();\n\t\t\t\t\t\tabstractDataSourceProperties.setEnv(env);\n\t\t\t\t\t\tabstractDataSourceProperties.preCheck(dataSourceName);\n\t\t\t\t\t\tregisterBean(abstractDataSourceProperties, dataSourceName\n\t\t\t\t\t\t\t\t+ \"-sentinel-\" + validFields.get(0) + \"-datasource\");\n\t\t\t\t\t}\n\t\t\t\t\tcatch (Exception e) {\n\t\t\t\t\t\tlog.error(\"[Sentinel Starter] DataSource \" + dataSourceName\n\t\t\t\t\t\t\t\t+ \" build error: \" + e.getMessage(), e);\n\t\t\t\t\t}\n\t\t\t\t});\n\t}\n\n\tprotected BeanDefinitionBuilder parseBeanDefinition(final AbstractDataSourceProperties dataSourceProperties,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tString dataSourceName) {\n\t\tMap<String, Object> propertyMap = Arrays\n\t\t\t\t.stream(dataSourceProperties.getClass().getDeclaredFields())\n\t\t\t\t.filter(field -> !field.isSynthetic())\n\t\t\t\t.collect(HashMap::new, (m, v) -> {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tv.setAccessible(true);\n\t\t\t\t\t\tm.put(v.getName(), v.get(dataSourceProperties));\n\t\t\t\t\t}\n\t\t\t\t\tcatch (IllegalAccessException e) {\n\t\t\t\t\t\tlog.error(\"[Sentinel Starter] DataSource \" + dataSourceName\n\t\t\t\t\t\t\t\t+ \" field: \" + v.getName() + \" invoke error\");\n\t\t\t\t\t\tthrow new RuntimeException(\n\t\t\t\t\t\t\t\t\"[Sentinel Starter] DataSource \" + dataSourceName\n\t\t\t\t\t\t\t\t\t\t+ \" field: \" + v.getName() + \" invoke error\",\n\t\t\t\t\t\t\t\te);\n\t\t\t\t\t}\n\t\t\t\t}, HashMap::putAll);\n\t\tpropertyMap.put(CONVERTER_CLASS_FIELD, dataSourceProperties.getConverterClass());\n\t\tpropertyMap.put(DATA_TYPE_FIELD, dataSourceProperties.getDataType());\n\n\t\tBeanDefinitionBuilder builder = BeanDefinitionBuilder\n\t\t\t\t.genericBeanDefinition(dataSourceProperties.getFactoryBeanName());\n\n\t\tpropertyMap.forEach((propertyName, propertyValue) -> {\n\t\t\tField field = ReflectionUtils.findField(dataSourceProperties.getClass(),\n\t\t\t\t\tpropertyName);\n\t\t\tif (null == field) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (DATA_TYPE_FIELD.equals(propertyName)) {\n\t\t\t\tString dataType = StringUtils.trimAllWhitespace(propertyValue.toString());\n\t\t\t\tif (CUSTOM_DATA_TYPE.equals(dataType)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!StringUtils\n\t\t\t\t\t\t\t\t.hasLength(dataSourceProperties.getConverterClass())) {\n\t\t\t\t\t\t\tthrow new RuntimeException(\"[Sentinel Starter] DataSource \"\n\t\t\t\t\t\t\t\t\t+ dataSourceName\n\t\t\t\t\t\t\t\t\t+ \"dataType is custom, please set converter-class \"\n\t\t\t\t\t\t\t\t\t+ \"property\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// construct custom Converter with 'converterClass'\n\t\t\t\t\t\t// configuration and register\n\t\t\t\t\t\tString customConvertBeanName = \"sentinel-\"\n\t\t\t\t\t\t\t\t+ dataSourceProperties.getConverterClass();\n\t\t\t\t\t\tif (!this.beanFactory.containsBean(customConvertBeanName)) {\n\t\t\t\t\t\t\tthis.beanFactory.registerBeanDefinition(customConvertBeanName,\n\t\t\t\t\t\t\t\t\tBeanDefinitionBuilder\n\t\t\t\t\t\t\t\t\t\t\t.genericBeanDefinition(\n\t\t\t\t\t\t\t\t\t\t\t\t\tClass.forName(dataSourceProperties\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.getConverterClass()))\n\t\t\t\t\t\t\t\t\t\t\t.getBeanDefinition());\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbuilder.addPropertyReference(\"converter\", customConvertBeanName);\n\t\t\t\t\t}\n\t\t\t\t\tcatch (ClassNotFoundException e) {\n\t\t\t\t\t\tlog.error(\"[Sentinel Starter] DataSource \" + dataSourceName\n\t\t\t\t\t\t\t\t+ \" handle \"\n\t\t\t\t\t\t\t\t+ dataSourceProperties.getClass().getSimpleName()\n\t\t\t\t\t\t\t\t+ \" error, class name: \"\n\t\t\t\t\t\t\t\t+ dataSourceProperties.getConverterClass());\n\t\t\t\t\t\tthrow new RuntimeException(\"[Sentinel Starter] DataSource \"\n\t\t\t\t\t\t\t\t+ dataSourceName + \" handle \"\n\t\t\t\t\t\t\t\t+ dataSourceProperties.getClass().getSimpleName()\n\t\t\t\t\t\t\t\t+ \" error, class name: \"\n\t\t\t\t\t\t\t\t+ dataSourceProperties.getConverterClass(), e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tif (!dataTypeList.contains(\n\t\t\t\t\t\t\tStringUtils.trimAllWhitespace(propertyValue.toString()))) {\n\t\t\t\t\t\tthrow new RuntimeException(\"[Sentinel Starter] DataSource \"\n\t\t\t\t\t\t\t\t+ dataSourceName + \" dataType: \" + propertyValue\n\t\t\t\t\t\t\t\t+ \" is not support now. please using these types: \"\n\t\t\t\t\t\t\t\t+ dataTypeList.toString());\n\t\t\t\t\t}\n\t\t\t\t\t// converter type now support xml or json.\n\t\t\t\t\t// The bean name of these converters wrapped by\n\t\t\t\t\t// 'sentinel-{converterType}-{ruleType}-converter'\n\t\t\t\t\tbuilder.addPropertyReference(\"converter\",\n\t\t\t\t\t\t\t\"sentinel-\" + propertyValue.toString() + \"-\"\n\t\t\t\t\t\t\t\t\t+ dataSourceProperties.getRuleType().getName()\n\t\t\t\t\t\t\t\t\t+ \"-converter\");\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (!CONVERTER_CLASS_FIELD.equals(propertyName)) {\n\t\t\t\t\t// wired properties\n\t\t\t\t\tOptional.ofNullable(propertyValue)\n\t\t\t\t\t\t\t.ifPresent(v -> builder.addPropertyValue(propertyName, v));\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn builder;\n\t}\n\n\tprivate void registerBean(final AbstractDataSourceProperties dataSourceProperties,\n\t\t\tString dataSourceName) {\n\t\tBeanDefinitionBuilder builder = parseBeanDefinition(dataSourceProperties, dataSourceName);\n\n\t\tthis.beanFactory.registerBeanDefinition(dataSourceName,\n\t\t\t\tbuilder.getBeanDefinition());\n\t\t// init in Spring\n\t\tAbstractDataSource newDataSource = (AbstractDataSource) this.beanFactory\n\t\t\t\t.getBean(dataSourceName);\n\n\t\t// register property in RuleManager\n\t\tdataSourceProperties.postRegister(newDataSource);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelProtectInterceptor.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.custom;\n\nimport java.io.IOException;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.net.URI;\n\nimport com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;\nimport com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;\nimport com.alibaba.csp.sentinel.Entry;\nimport com.alibaba.csp.sentinel.EntryType;\nimport com.alibaba.csp.sentinel.SphU;\nimport com.alibaba.csp.sentinel.Tracer;\nimport com.alibaba.csp.sentinel.slots.block.BlockException;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;\n\nimport org.springframework.http.HttpRequest;\nimport org.springframework.http.client.ClientHttpRequestExecution;\nimport org.springframework.http.client.ClientHttpRequestInterceptor;\nimport org.springframework.http.client.ClientHttpResponse;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * Interceptor using by SentinelRestTemplate.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class SentinelProtectInterceptor implements ClientHttpRequestInterceptor {\n\n\tprivate final SentinelRestTemplate sentinelRestTemplate;\n\n\tprivate final RestTemplate restTemplate;\n\n\tpublic SentinelProtectInterceptor(SentinelRestTemplate sentinelRestTemplate,\n\t\t\tRestTemplate restTemplate) {\n\t\tthis.sentinelRestTemplate = sentinelRestTemplate;\n\t\tthis.restTemplate = restTemplate;\n\t}\n\n\t@Override\n\tpublic ClientHttpResponse intercept(HttpRequest request, byte[] body,\n\t\t\tClientHttpRequestExecution execution) throws IOException {\n\t\tURI uri = request.getURI();\n\t\tString hostResource = request.getMethod().toString() + \":\" + uri.getScheme()\n\t\t\t\t+ \"://\" + uri.getHost()\n\t\t\t\t+ (uri.getPort() == -1 ? \"\" : \":\" + uri.getPort());\n\t\tString hostWithPathResource = hostResource + uri.getPath();\n\t\tboolean entryWithPath = true;\n\t\tif (hostResource.equals(hostWithPathResource)) {\n\t\t\tentryWithPath = false;\n\t\t}\n\t\tMethod urlCleanerMethod = BlockClassRegistry.lookupUrlCleaner(\n\t\t\t\tsentinelRestTemplate.urlCleanerClass(),\n\t\t\t\tsentinelRestTemplate.urlCleaner());\n\t\tif (urlCleanerMethod != null) {\n\t\t\thostWithPathResource = (String) methodInvoke(urlCleanerMethod,\n\t\t\t\t\thostWithPathResource);\n\t\t}\n\n\t\tEntry hostEntry = null;\n\t\tEntry hostWithPathEntry = null;\n\t\tClientHttpResponse response = null;\n\t\ttry {\n\t\t\thostEntry = SphU.entry(hostResource, EntryType.OUT);\n\t\t\tif (entryWithPath) {\n\t\t\t\thostWithPathEntry = SphU.entry(hostWithPathResource, EntryType.OUT);\n\t\t\t}\n\t\t\tresponse = execution.execute(request, body);\n\t\t\tif (this.restTemplate.getErrorHandler().hasError(response)) {\n\t\t\t\tTracer.trace(\n\t\t\t\t\t\tnew IllegalStateException(\"RestTemplate ErrorHandler has error\"));\n\t\t\t}\n\t\t\treturn response;\n\t\t}\n\t\tcatch (Throwable e) {\n\t\t\tif (BlockException.isBlockException(e)) {\n\t\t\t\treturn handleBlockException(request, body, execution, (BlockException) e);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tTracer.traceEntry(e, hostEntry);\n\t\t\t\tif (e instanceof IOException ioException) {\n\t\t\t\t\tthrow ioException;\n\t\t\t\t}\n\t\t\t\telse if (e instanceof RuntimeException runtimeException) {\n\t\t\t\t\tthrow runtimeException;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthrow new IOException(e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfinally {\n\t\t\tif (hostWithPathEntry != null) {\n\t\t\t\thostWithPathEntry.exit();\n\t\t\t}\n\t\t\tif (hostEntry != null) {\n\t\t\t\thostEntry.exit();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate ClientHttpResponse handleBlockException(HttpRequest request, byte[] body,\n\t\t\tClientHttpRequestExecution execution, BlockException ex) {\n\t\tObject[] args = new Object[] { request, body, execution, ex };\n\t\t// handle degrade\n\t\tif (isDegradeFailure(ex)) {\n\t\t\tMethod fallbackMethod = extractFallbackMethod(sentinelRestTemplate.fallback(),\n\t\t\t\t\tsentinelRestTemplate.fallbackClass());\n\t\t\tif (fallbackMethod != null) {\n\t\t\t\treturn (ClientHttpResponse) methodInvoke(fallbackMethod, args);\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn new SentinelClientHttpResponse();\n\t\t\t}\n\t\t}\n\t\t// handle flow\n\t\tMethod blockHandler = extractBlockHandlerMethod(\n\t\t\t\tsentinelRestTemplate.blockHandler(),\n\t\t\t\tsentinelRestTemplate.blockHandlerClass());\n\t\tif (blockHandler != null) {\n\t\t\treturn (ClientHttpResponse) methodInvoke(blockHandler, args);\n\t\t}\n\t\telse {\n\t\t\treturn new SentinelClientHttpResponse();\n\t\t}\n\t}\n\n\tprivate Object methodInvoke(Method method, Object... args) {\n\t\ttry {\n\t\t\treturn method.invoke(null, args);\n\t\t}\n\t\tcatch (IllegalAccessException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\tcatch (InvocationTargetException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\tprivate Method extractFallbackMethod(String fallback, Class<?> fallbackClass) {\n\t\treturn BlockClassRegistry.lookupFallback(fallbackClass, fallback);\n\t}\n\n\tprivate Method extractBlockHandlerMethod(String block, Class<?> blockClass) {\n\t\treturn BlockClassRegistry.lookupBlockHandler(blockClass, block);\n\t}\n\n\tprivate boolean isDegradeFailure(BlockException ex) {\n\t\treturn ex instanceof DegradeException;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/context/SentinelApplicationContextInitializer.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.custom.context;\n\nimport com.alibaba.cloud.commons.lang.StringUtils;\nimport com.alibaba.cloud.sentinel.SentinelConstants;\nimport com.alibaba.cloud.sentinel.SentinelProperties;\nimport com.alibaba.csp.sentinel.config.SentinelConfig;\nimport com.alibaba.csp.sentinel.init.InitExecutor;\nimport com.alibaba.csp.sentinel.log.LogBase;\nimport com.alibaba.csp.sentinel.transport.config.TransportConfig;\n\nimport org.springframework.boot.context.properties.bind.Binder;\nimport org.springframework.context.ApplicationContextInitializer;\nimport org.springframework.context.ConfigurableApplicationContext;\nimport org.springframework.core.env.ConfigurableEnvironment;\n\nimport static com.alibaba.cloud.sentinel.SentinelConstants.BLOCK_PAGE_URL_CONF_KEY;\nimport static com.alibaba.csp.sentinel.config.SentinelConfig.setConfig;\n\n/**\n * @author yuluo\n * @author <a href=\"mailto:yuluo08290126@gmail.com\">yuluo</a>\n */\n\npublic class SentinelApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {\n\n\t@Override\n\tpublic void initialize(ConfigurableApplicationContext applicationContext) {\n\n\t\tConfigurableEnvironment environment = applicationContext.getEnvironment();\n\t\tString applicationName = environment.getProperty(\"spring.application.name\");\n\t\tSentinelProperties sentinelProperties = Binder.get(environment)\n\t\t\t\t.bindOrCreate(SentinelConstants.PROPERTY_PREFIX, SentinelProperties.class);\n\n\t\tinitSentinelConfig(sentinelProperties, applicationName);\n\t}\n\n\tprivate void initSentinelConfig(SentinelProperties properties, String applicationName) {\n\n\t\tif (StringUtils.isEmpty(System.getProperty(LogBase.LOG_DIR))\n\t\t\t\t&& StringUtils.isNotBlank(properties.getLog().getDir())) {\n\t\t\tSystem.setProperty(LogBase.LOG_DIR, properties.getLog().getDir());\n\t\t}\n\t\tif (StringUtils.isEmpty(System.getProperty(LogBase.LOG_NAME_USE_PID))\n\t\t\t\t&& properties.getLog().isSwitchPid()) {\n\t\t\tSystem.setProperty(LogBase.LOG_NAME_USE_PID,\n\t\t\t\t\tString.valueOf(properties.getLog().isSwitchPid()));\n\t\t}\n\t\tif (StringUtils.isEmpty(System.getProperty(SentinelConfig.APP_NAME_PROP_KEY))\n\t\t\t\t&& StringUtils.isNotBlank(applicationName)) {\n\t\t\tSystem.setProperty(SentinelConfig.APP_NAME_PROP_KEY, applicationName);\n\t\t}\n\t\tif (StringUtils.isEmpty(System.getProperty(TransportConfig.SERVER_PORT))\n\t\t\t\t&& StringUtils.isNotBlank(properties.getTransport().getPort())) {\n\t\t\tSystem.setProperty(TransportConfig.SERVER_PORT,\n\t\t\t\t\tproperties.getTransport().getPort());\n\t\t}\n\t\tif (StringUtils.isEmpty(System.getProperty(TransportConfig.CONSOLE_SERVER))\n\t\t\t\t&& StringUtils.isNotBlank(properties.getTransport().getDashboard())) {\n\t\t\tSystem.setProperty(TransportConfig.CONSOLE_SERVER,\n\t\t\t\t\tproperties.getTransport().getDashboard());\n\t\t}\n\t\tif (StringUtils.isEmpty(System.getProperty(TransportConfig.HEARTBEAT_INTERVAL_MS))\n\t\t\t\t&& StringUtils\n\t\t\t\t.isNotBlank(properties.getTransport().getHeartbeatIntervalMs())) {\n\t\t\tSystem.setProperty(TransportConfig.HEARTBEAT_INTERVAL_MS,\n\t\t\t\t\tproperties.getTransport().getHeartbeatIntervalMs());\n\t\t}\n\t\tif (StringUtils.isEmpty(System.getProperty(TransportConfig.HEARTBEAT_CLIENT_IP))\n\t\t\t\t&& StringUtils.isNotBlank(properties.getTransport().getClientIp())) {\n\t\t\tSystem.setProperty(TransportConfig.HEARTBEAT_CLIENT_IP,\n\t\t\t\t\tproperties.getTransport().getClientIp());\n\t\t}\n\t\tif (StringUtils.isEmpty(System.getProperty(SentinelConfig.CHARSET))\n\t\t\t\t&& StringUtils.isNotBlank(properties.getMetric().getCharset())) {\n\t\t\tSystem.setProperty(SentinelConfig.CHARSET,\n\t\t\t\t\tproperties.getMetric().getCharset());\n\t\t}\n\t\tif (StringUtils\n\t\t\t\t.isEmpty(System.getProperty(SentinelConfig.SINGLE_METRIC_FILE_SIZE))\n\t\t\t\t&& StringUtils.isNotBlank(properties.getMetric().getFileSingleSize())) {\n\t\t\tSystem.setProperty(SentinelConfig.SINGLE_METRIC_FILE_SIZE,\n\t\t\t\t\tproperties.getMetric().getFileSingleSize());\n\t\t}\n\t\tif (StringUtils\n\t\t\t\t.isEmpty(System.getProperty(SentinelConfig.TOTAL_METRIC_FILE_COUNT))\n\t\t\t\t&& StringUtils.isNotBlank(properties.getMetric().getFileTotalCount())) {\n\t\t\tSystem.setProperty(SentinelConfig.TOTAL_METRIC_FILE_COUNT,\n\t\t\t\t\tproperties.getMetric().getFileTotalCount());\n\t\t}\n\t\tif (StringUtils.isEmpty(System.getProperty(SentinelConfig.COLD_FACTOR))\n\t\t\t\t&& StringUtils.isNotBlank(properties.getFlow().getColdFactor())) {\n\t\t\tSystem.setProperty(SentinelConfig.COLD_FACTOR,\n\t\t\t\t\tproperties.getFlow().getColdFactor());\n\t\t}\n\t\tif (StringUtils.isNotBlank(properties.getBlockPage())) {\n\t\t\tsetConfig(BLOCK_PAGE_URL_CONF_KEY, properties.getBlockPage());\n\t\t}\n\n\t\t// earlier initialize\n\t\tif (properties.isEager()) {\n\n\t\t\tInitExecutor.doInit();\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelEndpoint.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.endpoint;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport com.alibaba.cloud.sentinel.SentinelProperties;\nimport com.alibaba.csp.sentinel.config.SentinelConfig;\nimport com.alibaba.csp.sentinel.log.LogBase;\nimport com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;\nimport com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;\nimport com.alibaba.csp.sentinel.slots.system.SystemRuleManager;\nimport com.alibaba.csp.sentinel.transport.config.TransportConfig;\nimport com.alibaba.csp.sentinel.util.AppNameUtil;\n\nimport org.springframework.boot.actuate.endpoint.annotation.Endpoint;\nimport org.springframework.boot.actuate.endpoint.annotation.ReadOperation;\n\nimport static com.alibaba.cloud.sentinel.SentinelConstants.BLOCK_PAGE_URL_CONF_KEY;\n\n/**\n * Endpoint for Sentinel, contains ans properties and rules.\n *\n * @author xiaojing\n */\n@Endpoint(id = \"sentinel\")\npublic class SentinelEndpoint {\n\n\tprivate final SentinelProperties sentinelProperties;\n\n\tpublic SentinelEndpoint(SentinelProperties sentinelProperties) {\n\t\tthis.sentinelProperties = sentinelProperties;\n\t}\n\n\t@ReadOperation\n\tpublic Map<String, Object> invoke() {\n\t\tfinal Map<String, Object> result = new HashMap<>();\n\t\tif (sentinelProperties.isEnabled()) {\n\n\t\t\tresult.put(\"appName\", AppNameUtil.getAppName());\n\t\t\tresult.put(\"logDir\", LogBase.getLogBaseDir());\n\t\t\tresult.put(\"logUsePid\", LogBase.isLogNameUsePid());\n\t\t\tresult.put(\"blockPage\", SentinelConfig.getConfig(BLOCK_PAGE_URL_CONF_KEY));\n\t\t\tresult.put(\"metricsFileSize\", SentinelConfig.singleMetricFileSize());\n\t\t\tresult.put(\"metricsFileCharset\", SentinelConfig.charset());\n\t\t\tresult.put(\"totalMetricsFileCount\", SentinelConfig.totalMetricFileCount());\n\t\t\tresult.put(\"consoleServer\", TransportConfig.getConsoleServerList());\n\t\t\tresult.put(\"clientIp\", TransportConfig.getHeartbeatClientIp());\n\t\t\tresult.put(\"heartbeatIntervalMs\", TransportConfig.getHeartbeatIntervalMs());\n\t\t\tresult.put(\"clientPort\", TransportConfig.getPort());\n\t\t\tresult.put(\"coldFactor\", sentinelProperties.getFlow().getColdFactor());\n\t\t\tresult.put(\"filter\", sentinelProperties.getFilter());\n\t\t\tresult.put(\"datasource\", sentinelProperties.getDatasource());\n\n\t\t\tfinal Map<String, Object> rules = new HashMap<>();\n\t\t\tresult.put(\"rules\", rules);\n\t\t\trules.put(\"flowRules\", FlowRuleManager.getRules());\n\t\t\trules.put(\"degradeRules\", DegradeRuleManager.getRules());\n\t\t\trules.put(\"systemRules\", SystemRuleManager.getRules());\n\t\t\trules.put(\"authorityRule\", AuthorityRuleManager.getRules());\n\t\t\trules.put(\"paramFlowRule\", ParamFlowRuleManager.getRules());\n\t\t}\n\t\treturn result;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelEndpointAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.endpoint;\n\nimport com.alibaba.cloud.sentinel.SentinelProperties;\n\nimport org.springframework.beans.factory.support.DefaultListableBeanFactory;\nimport org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;\nimport org.springframework.boot.actuate.endpoint.annotation.Endpoint;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator;\nimport org.springframework.context.annotation.Bean;\n\n/**\n * @author hengyunabc\n */\n@ConditionalOnClass(Endpoint.class)\n@EnableConfigurationProperties({ SentinelProperties.class })\npublic class SentinelEndpointAutoConfiguration {\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\t@ConditionalOnAvailableEndpoint\n\tpublic SentinelEndpoint sentinelEndPoint(SentinelProperties sentinelProperties) {\n\t\treturn new SentinelEndpoint(sentinelProperties);\n\t}\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\t@ConditionalOnEnabledHealthIndicator(\"sentinel\")\n\tpublic SentinelHealthIndicator sentinelHealthIndicator(\n\t\t\tDefaultListableBeanFactory beanFactory,\n\t\t\tSentinelProperties sentinelProperties) {\n\t\treturn new SentinelHealthIndicator(beanFactory, sentinelProperties);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelHealthIndicator.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.endpoint;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.alibaba.cloud.sentinel.SentinelProperties;\nimport com.alibaba.csp.sentinel.datasource.AbstractDataSource;\nimport com.alibaba.csp.sentinel.heartbeat.HeartbeatSenderProvider;\nimport com.alibaba.csp.sentinel.transport.HeartbeatSender;\nimport com.alibaba.csp.sentinel.transport.config.TransportConfig;\nimport com.alibaba.csp.sentinel.transport.endpoint.Endpoint;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.support.DefaultListableBeanFactory;\nimport org.springframework.boot.health.contributor.AbstractHealthIndicator;\nimport org.springframework.boot.health.contributor.Health;\nimport org.springframework.boot.health.contributor.HealthIndicator;\nimport org.springframework.boot.health.contributor.Status;\nimport org.springframework.util.CollectionUtils;\n\n/**\n * A {@link HealthIndicator} for Sentinel, which checks the status of Sentinel Dashboard\n * and DataSource.\n *\n * <p>\n * Check the status of Sentinel Dashboard by sending a heartbeat message to it. If return\n * true, it's OK.\n *\n * Check the status of Sentinel DataSource by calling loadConfig method of\n * {@link AbstractDataSource}. If no Exception thrown, it's OK.\n *\n * If Dashboard and DataSource are both OK, the health status is UP.\n * </p>\n *\n * <p>\n * Note: If Sentinel isn't enabled, the health status is up. If Sentinel Dashboard isn't\n * configured, it's OK and mark the status of Dashboard with UNKNOWN. More informations\n * are provided in details.\n * </p>\n *\n * @author cdfive\n */\npublic class SentinelHealthIndicator extends AbstractHealthIndicator {\n\n\tprivate DefaultListableBeanFactory beanFactory;\n\n\tprivate SentinelProperties sentinelProperties;\n\n\tprivate static final Logger logger = LoggerFactory.getLogger(SentinelHealthIndicator.class);\n\n\tpublic SentinelHealthIndicator(DefaultListableBeanFactory beanFactory,\n\t\t\tSentinelProperties sentinelProperties) {\n\t\tthis.beanFactory = beanFactory;\n\t\tthis.sentinelProperties = sentinelProperties;\n\t}\n\n\t@Override\n\tprotected void doHealthCheck(Health.Builder builder) throws Exception {\n\t\tMap<String, Object> detailMap = new HashMap<>();\n\n\t\t// If sentinel isn't enabled, set the status up and set the enabled to false in\n\t\t// detail\n\t\tif (!sentinelProperties.isEnabled()) {\n\t\t\tdetailMap.put(\"enabled\", false);\n\t\t\tbuilder.up().withDetails(detailMap);\n\t\t\treturn;\n\t\t}\n\n\t\tdetailMap.put(\"enabled\", true);\n\n\t\t// Check health of Dashboard\n\t\tboolean dashboardUp = true;\n\t\tList<Endpoint> consoleServerList = TransportConfig.getConsoleServerList();\n\t\tlogger.info(\"Find sentinel dashboard server list: {}\", consoleServerList);\n\t\tif (CollectionUtils.isEmpty(consoleServerList)) {\n\t\t\t// If Dashboard isn't configured, it's OK and mark the status of Dashboard\n\t\t\t// with UNKNOWN.\n\t\t\tdetailMap.put(\"dashboard\",\n\t\t\t\t\tnew Status(\n\t\t\t\t\t\t\tStatus.UNKNOWN.getCode(),\n\t\t\t\t\t\t\t\"dashboard isn't configured\"\n\t\t\t\t\t)\n\t\t\t);\n\t\t}\n\t\telse {\n\t\t\t// If Dashboard is configured, send a heartbeat message to it and check the\n\t\t\tHeartbeatSender heartbeatSender = HeartbeatSenderProvider.getHeartbeatSender();\n\t\t\t// result is true if the heartbeat message is sent successfully\n\t\t\tboolean result = heartbeatSender.sendHeartbeat();\n\t\t\tif (result) {\n\t\t\t\tdetailMap.put(\"dashboard\", Status.UP);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlogger.warn(\"Sentinel dashboard heartbeat message can't be sent to the dashboard servers {} one of them can't be connected\",\n\t\t\t\t\t\tconsoleServerList);\n\t\t\t\t// If failed to send heartbeat message, means that the Dashboard is DOWN\n\t\t\t\tdashboardUp = false;\n\t\t\t\tdetailMap.put(\"dashboard\", new Status(\n\t\t\t\t\t\tStatus.UNKNOWN.getCode(),\n\t\t\t\t\t\tString.format(\n\t\t\t\t\t\t\t\t\"the dashboard servers [%s] one of them can't be connected\",\n\t\t\t\t\t\t\t\tconsoleServerList\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Check health of DataSource\n\t\tboolean dataSourceUp = true;\n\t\tMap<String, Object> dataSourceDetailMap = new HashMap<>();\n\t\tdetailMap.put(\"dataSource\", dataSourceDetailMap);\n\n\t\t// Get all DataSources and each call loadConfig to check if it's OK\n\t\t// If no Exception thrown, it's OK\n\t\t// Note:\n\t\t// Even if the dynamic config center is down, the loadConfig() might return\n\t\t// successfully\n\t\t// e.g. for Nacos client, it might retrieve from the local cache)\n\t\t// But in most circumstances it's okay\n\t\tMap<String, AbstractDataSource> dataSourceMap = beanFactory\n\t\t\t\t.getBeansOfType(AbstractDataSource.class);\n\t\tfor (Map.Entry<String, AbstractDataSource> dataSourceMapEntry : dataSourceMap\n\t\t\t\t.entrySet()) {\n\t\t\tString dataSourceBeanName = dataSourceMapEntry.getKey();\n\t\t\tAbstractDataSource dataSource = dataSourceMapEntry.getValue();\n\t\t\ttry {\n\t\t\t\tdataSource.loadConfig();\n\t\t\t\tdataSourceDetailMap.put(dataSourceBeanName, Status.UP);\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\t\t\t\t// If one DataSource failed to loadConfig, means that the DataSource is\n\t\t\t\t// DOWN\n\t\t\t\tdataSourceUp = false;\n\t\t\t\tdataSourceDetailMap.put(dataSourceBeanName,\n\t\t\t\t\t\tnew Status(Status.UNKNOWN.getCode(), e.getMessage()));\n\t\t\t}\n\t\t}\n\n\t\t// If Dashboard and DataSource are both OK, the health status is UP\n\t\tif (dashboardUp && dataSourceUp) {\n\t\t\tbuilder.up().withDetails(detailMap);\n\t\t}\n\t\telse {\n\t\t\tbuilder.unknown().withDetails(detailMap);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelContractHolder.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.feign;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport feign.Contract;\nimport feign.MethodMetadata;\n\n/**\n *\n * Using static field {@link SentinelContractHolder#METADATA_MAP} to hold\n * {@link MethodMetadata} data.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class SentinelContractHolder implements Contract {\n\n\tprivate final Contract delegate;\n\n\t/**\n\t * map key is constructed by ClassFullName + configKey. configKey is constructed by\n\t * {@link feign.Feign#configKey}\n\t */\n\tpublic final static Map<String, MethodMetadata> METADATA_MAP = new HashMap<>();\n\n\tpublic SentinelContractHolder(Contract delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n\t@Override\n\tpublic List<MethodMetadata> parseAndValidateMetadata(Class<?> targetType) {\n\t\tList<MethodMetadata> metadatas = delegate.parseAndValidateMetadata(targetType);\n\t\tmetadatas.forEach(metadata -> METADATA_MAP\n\t\t\t\t.put(targetType.getName() + metadata.configKey(), metadata));\n\t\treturn metadatas;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.feign;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Method;\nimport java.util.Map;\n\nimport feign.Contract;\nimport feign.Feign;\nimport feign.InvocationHandlerFactory;\nimport feign.Target;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.FactoryBean;\nimport org.springframework.beans.factory.config.BeanDefinition;\nimport org.springframework.cloud.openfeign.FallbackFactory;\nimport org.springframework.cloud.openfeign.FeignClientFactory;\nimport org.springframework.cloud.openfeign.FeignClientFactoryBean;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.context.support.GenericApplicationContext;\nimport org.springframework.util.ReflectionUtils;\nimport org.springframework.util.StringUtils;\n\n/**\n * {@link Feign.Builder}.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n * @author 黄学敏（huangxuemin)\n */\npublic final class SentinelFeign {\n\n\tprivate static final String FEIGN_LAZY_ATTR_RESOLUTION = \"spring.cloud.openfeign.lazy-attributes-resolution\";\n\n\tprivate SentinelFeign() {\n\n\t}\n\n\tpublic static Builder builder() {\n\t\treturn new Builder();\n\t}\n\n\tpublic static final class Builder extends Feign.Builder\n\t\t\timplements ApplicationContextAware {\n\n\t\tprivate Contract contract = new Contract.Default();\n\n\t\tprivate ApplicationContext applicationContext;\n\n\t\tprivate FeignClientFactory feignClientFactory;\n\n\t\t@Override\n\t\tpublic Feign.Builder invocationHandlerFactory(\n\t\t\t\tInvocationHandlerFactory invocationHandlerFactory) {\n\t\t\tthrow new UnsupportedOperationException();\n\t\t}\n\n\t\t@Override\n\t\tpublic Builder contract(Contract contract) {\n\t\t\tthis.contract = contract;\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic Feign internalBuild() {\n\t\t\tsuper.invocationHandlerFactory(new InvocationHandlerFactory() {\n\t\t\t\t@Override\n\t\t\t\tpublic InvocationHandler create(Target target,\n\t\t\t\t\t\tMap<Method, MethodHandler> dispatch) {\n\t\t\t\t\tGenericApplicationContext gctx = (GenericApplicationContext) Builder.this.applicationContext;\n\t\t\t\t\tBeanDefinition def = gctx.getBeanDefinition(target.type().getName());\n\t\t\t\t\tFeignClientFactoryBean feignClientFactoryBean;\n\n\t\t\t\t\t// If you need the attributes to be resolved lazily, set the property value to true.\n\t\t\t\t\tBoolean isLazyInit = applicationContext.getEnvironment()\n\t\t\t\t\t\t\t.getProperty(FEIGN_LAZY_ATTR_RESOLUTION, Boolean.class, false);\n\t\t\t\t\tif (isLazyInit) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t * Due to the change of the initialization sequence,\n\t\t\t\t\t\t * BeanFactory.getBean will cause a circular dependency. So\n\t\t\t\t\t\t * FeignClientFactoryBean can only be obtained from BeanDefinition\n\t\t\t\t\t\t */\n\t\t\t\t\t\tfeignClientFactoryBean = (FeignClientFactoryBean) def\n\t\t\t\t\t\t\t\t.getAttribute(\"feignClientsRegistrarFactoryBean\");\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tfeignClientFactoryBean = (FeignClientFactoryBean) applicationContext\n\t\t\t\t\t\t\t\t.getBean(\"&\" + target.type().getName());\n\t\t\t\t\t}\n\t\t\t\t\tClass fallback = feignClientFactoryBean.getFallback();\n\t\t\t\t\tClass fallbackFactory = feignClientFactoryBean.getFallbackFactory();\n\t\t\t\t\tString beanName = feignClientFactoryBean.getContextId();\n\t\t\t\t\tif (!StringUtils.hasText(beanName)) {\n\t\t\t\t\t\tbeanName = (String) getFieldValue(feignClientFactoryBean, \"name\");\n\t\t\t\t\t}\n\n\t\t\t\t\tObject fallbackInstance;\n\t\t\t\t\tFallbackFactory fallbackFactoryInstance;\n\t\t\t\t\t// check fallback and fallbackFactory properties\n\t\t\t\t\tif (void.class != fallback) {\n\t\t\t\t\t\tfallbackInstance = getFromContext(beanName, \"fallback\", fallback,\n\t\t\t\t\t\t\t\ttarget.type());\n\t\t\t\t\t\treturn new SentinelInvocationHandler(target, dispatch,\n\t\t\t\t\t\t\t\tnew FallbackFactory.Default(fallbackInstance));\n\t\t\t\t\t}\n\t\t\t\t\tif (void.class != fallbackFactory) {\n\t\t\t\t\t\tfallbackFactoryInstance = (FallbackFactory) getFromContext(\n\t\t\t\t\t\t\t\tbeanName, \"fallbackFactory\", fallbackFactory,\n\t\t\t\t\t\t\t\tFallbackFactory.class);\n\t\t\t\t\t\treturn new SentinelInvocationHandler(target, dispatch,\n\t\t\t\t\t\t\t\tfallbackFactoryInstance);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn new SentinelInvocationHandler(target, dispatch);\n\t\t\t\t}\n\n\t\t\t\tprivate Object getFromContext(String name, String type,\n\t\t\t\t\t\tClass fallbackType, Class targetType) {\n\t\t\t\t\tObject fallbackInstance = feignClientFactory.getInstance(name,\n\t\t\t\t\t\t\tfallbackType);\n\t\t\t\t\tif (fallbackInstance == null) {\n\t\t\t\t\t\tthrow new IllegalStateException(String.format(\n\t\t\t\t\t\t\t\t\"No %s instance of type %s found for feign client %s\",\n\t\t\t\t\t\t\t\ttype, fallbackType, name));\n\t\t\t\t\t}\n\t\t\t\t\t// when fallback is a FactoryBean, should determine the type of instance\n\t\t\t\t\tif (fallbackInstance instanceof FactoryBean<?> factoryBean) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tfallbackInstance = factoryBean.getObject();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (Exception e) {\n\t\t\t\t\t\t\tthrow new IllegalStateException(type + \" create fail\", e);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfallbackType = fallbackInstance.getClass();\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!targetType.isAssignableFrom(fallbackType)) {\n\t\t\t\t\t\tthrow new IllegalStateException(String.format(\n\t\t\t\t\t\t\t\t\"Incompatible %s instance. Fallback/fallbackFactory of type %s is not assignable to %s for feign client %s\",\n\t\t\t\t\t\t\t\ttype, fallbackType, targetType, name));\n\t\t\t\t\t}\n\t\t\t\t\treturn fallbackInstance;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tsuper.contract(new SentinelContractHolder(contract));\n\t\t\treturn super.internalBuild();\n\t\t}\n\n\t\tprivate Object getFieldValue(Object instance, String fieldName) {\n\t\t\tField field = ReflectionUtils.findField(instance.getClass(), fieldName);\n\t\t\tfield.setAccessible(true);\n\t\t\ttry {\n\t\t\t\treturn field.get(instance);\n\t\t\t}\n\t\t\tcatch (IllegalAccessException e) {\n\t\t\t\t// ignore\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tpublic void setApplicationContext(ApplicationContext applicationContext)\n\t\t\t\tthrows BeansException {\n\t\t\tthis.applicationContext = applicationContext;\n\t\t\tfeignClientFactory = this.applicationContext.getBean(FeignClientFactory.class);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeignAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.feign;\n\nimport com.alibaba.csp.sentinel.SphU;\nimport feign.Feign;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Scope;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnClass({ SphU.class, Feign.class })\npublic class SentinelFeignAutoConfiguration {\n\n\t@Bean\n\t@Scope(\"prototype\")\n\t@ConditionalOnMissingBean\n\t@ConditionalOnProperty(name = \"feign.sentinel.enabled\")\n\tpublic Feign.Builder feignSentinelBuilder() {\n\t\treturn SentinelFeign.builder();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelInvocationHandler.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.feign;\n\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Proxy;\nimport java.util.LinkedHashMap;\nimport java.util.Locale;\nimport java.util.Map;\n\nimport com.alibaba.csp.sentinel.Entry;\nimport com.alibaba.csp.sentinel.EntryType;\nimport com.alibaba.csp.sentinel.SphU;\nimport com.alibaba.csp.sentinel.Tracer;\nimport com.alibaba.csp.sentinel.context.ContextUtil;\nimport com.alibaba.csp.sentinel.slots.block.BlockException;\nimport feign.Feign;\nimport feign.InvocationHandlerFactory.MethodHandler;\nimport feign.MethodMetadata;\nimport feign.Target;\n\nimport org.springframework.cloud.openfeign.FallbackFactory;\n\nimport static feign.Util.checkNotNull;\n\n/**\n * {@link InvocationHandler} handle invocation that protected by Sentinel.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class SentinelInvocationHandler implements InvocationHandler {\n\n\tprivate final Target<?> target;\n\n\tprivate final Map<Method, MethodHandler> dispatch;\n\n\tprivate FallbackFactory fallbackFactory;\n\n\tprivate Map<Method, Method> fallbackMethodMap;\n\n\tSentinelInvocationHandler(Target<?> target, Map<Method, MethodHandler> dispatch,\n\t\t\tFallbackFactory fallbackFactory) {\n\t\tthis.target = checkNotNull(target, \"target\");\n\t\tthis.dispatch = checkNotNull(dispatch, \"dispatch\");\n\t\tthis.fallbackFactory = fallbackFactory;\n\t\tthis.fallbackMethodMap = toFallbackMethod(dispatch);\n\t}\n\n\tSentinelInvocationHandler(Target<?> target, Map<Method, MethodHandler> dispatch) {\n\t\tthis.target = checkNotNull(target, \"target\");\n\t\tthis.dispatch = checkNotNull(dispatch, \"dispatch\");\n\t}\n\n\t@Override\n\tpublic Object invoke(final Object proxy, final Method method, final Object[] args)\n\t\t\tthrows Throwable {\n\t\tif (\"equals\".equals(method.getName())) {\n\t\t\ttry {\n\t\t\t\tObject otherHandler = args.length > 0 && args[0] != null\n\t\t\t\t\t\t? Proxy.getInvocationHandler(args[0])\n\t\t\t\t\t\t: null;\n\t\t\t\treturn equals(otherHandler);\n\t\t\t}\n\t\t\tcatch (IllegalArgumentException e) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\telse if (\"hashCode\".equals(method.getName())) {\n\t\t\treturn hashCode();\n\t\t}\n\t\telse if (\"toString\".equals(method.getName())) {\n\t\t\treturn toString();\n\t\t}\n\n\t\tObject result;\n\t\tMethodHandler methodHandler = this.dispatch.get(method);\n\t\t// only handle by HardCodedTarget\n\t\tif (target instanceof Target.HardCodedTarget hardCodedTarget) {\n\t\t\tMethodMetadata methodMetadata = SentinelContractHolder.METADATA_MAP\n\t\t\t\t\t.get(hardCodedTarget.type().getName()\n\t\t\t\t\t\t\t+ Feign.configKey(hardCodedTarget.type(), method));\n\t\t\t// resource default is HttpMethod:protocol://url\n\t\t\tif (methodMetadata == null) {\n\t\t\t\tresult = methodHandler.invoke(args);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tString resourceName = methodMetadata.template().method().toUpperCase(Locale.ROOT)\n\t\t\t\t\t\t+ \":\" + hardCodedTarget.url() + methodMetadata.template().path();\n\t\t\t\tEntry entry = null;\n\t\t\t\ttry {\n\t\t\t\t\tContextUtil.enter(resourceName);\n\t\t\t\t\tentry = SphU.entry(resourceName, EntryType.OUT, 1, args);\n\t\t\t\t\tresult = methodHandler.invoke(args);\n\t\t\t\t}\n\t\t\t\tcatch (Throwable ex) {\n\t\t\t\t\t// fallback handle\n\t\t\t\t\tif (!BlockException.isBlockException(ex)) {\n\t\t\t\t\t\tTracer.traceEntry(ex, entry);\n\t\t\t\t\t}\n\t\t\t\t\tif (fallbackFactory != null) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tObject fallbackResult = fallbackMethodMap.get(method)\n\t\t\t\t\t\t\t\t\t.invoke(fallbackFactory.create(ex), args);\n\t\t\t\t\t\t\treturn fallbackResult;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (IllegalAccessException e) {\n\t\t\t\t\t\t\t// shouldn't happen as method is public due to being an\n\t\t\t\t\t\t\t// interface\n\t\t\t\t\t\t\tthrow new AssertionError(e);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (InvocationTargetException e) {\n\t\t\t\t\t\t\tthrow e.getCause();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\t// throw exception if fallbackFactory is null\n\t\t\t\t\t\tthrow ex;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfinally {\n\t\t\t\t\tif (entry != null) {\n\t\t\t\t\t\tentry.exit(1, args);\n\t\t\t\t\t}\n\t\t\t\t\tContextUtil.exit();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t// other target type using default strategy\n\t\t\tresult = methodHandler.invoke(args);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object obj) {\n\t\tif (obj instanceof SentinelInvocationHandler sentinelInvocationHandler) {\n\t\t\treturn target.equals(sentinelInvocationHandler.target);\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn target.hashCode();\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn target.toString();\n\t}\n\n\tstatic Map<Method, Method> toFallbackMethod(Map<Method, MethodHandler> dispatch) {\n\t\tMap<Method, Method> result = new LinkedHashMap<>();\n\t\tfor (Method method : dispatch.keySet()) {\n\t\t\tmethod.setAccessible(true);\n\t\t\tresult.put(method, method);\n\t\t}\n\t\treturn result;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/rest/SentinelClientHttpResponse.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.rest;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;\nimport com.alibaba.cloud.sentinel.custom.SentinelProtectInterceptor;\n\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.client.ClientHttpResponse;\n\n/**\n * Using by {@link SentinelRestTemplate} and {@link SentinelProtectInterceptor}.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class SentinelClientHttpResponse implements ClientHttpResponse {\n\n\tprivate String blockResponse = \"RestTemplate request block by sentinel\";\n\n\tpublic SentinelClientHttpResponse() {\n\t}\n\n\tpublic SentinelClientHttpResponse(String blockResponse) {\n\t\tthis.blockResponse = blockResponse;\n\t}\n\n\t// @Override\n\tpublic int getRawStatusCode() throws IOException {\n\t\treturn HttpStatus.OK.value();\n\t}\n\n\t@Override\n\tpublic HttpStatus getStatusCode() throws IOException {\n\t\treturn HttpStatus.OK;\n\t}\n\n\t@Override\n\tpublic String getStatusText() throws IOException {\n\t\treturn blockResponse;\n\t}\n\n\t@Override\n\tpublic void close() {\n\t\t// nothing do\n\t}\n\n\t@Override\n\tpublic InputStream getBody() throws IOException {\n\t\treturn new ByteArrayInputStream(blockResponse.getBytes());\n\t}\n\n\t@Override\n\tpublic HttpHeaders getHeaders() {\n\t\tMap<String, List<String>> headers = new HashMap<>();\n\t\theaders.put(HttpHeaders.CONTENT_TYPE,\n\t\t\t\tArrays.asList(MediaType.APPLICATION_JSON_VALUE));\n\t\tHttpHeaders httpHeaders = new HttpHeaders();\n\t\thttpHeaders.putAll(headers);\n\t\treturn httpHeaders;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json",
    "content": "{\n  \"properties\": [\n    {\n      \"name\": \"spring.cloud.sentinel.enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": true,\n      \"description\": \"enable or disable sentinel auto configure.\"\n    },\n    {\n      \"name\": \"resttemplate.sentinel.enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": true,\n      \"description\": \"enable or disable @SentinelRestTemplate.\"\n    },\n    {\n      \"name\": \"spring.cloud.sentinel.eager\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": false,\n      \"description\": \"earlier initialize heart-beat when the spring container starts when the transport dependency is on classpath, the configuration is effective.\"\n    },\n    {\n      \"name\": \"spring.cloud.sentinel.web-context-unify\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": true,\n      \"description\": \"Specify whether unify web context(i.e. use the default context name), and is true by default.\"\n    },\n    {\n      \"name\": \"spring.cloud.sentinel.transport.port\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"8719\",\n      \"description\": \"sentinel api port.\"\n    },\n    {\n      \"name\": \"spring.cloud.sentinel.transport.clientIp\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"sentinel client ip connect to dashboard.\"\n    },\n    {\n      \"name\": \"spring.cloud.sentinel.transport.dashboard\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"sentinel dashboard address, won't try to connect dashboard when address is empty.\"\n    },\n    {\n      \"name\": \"spring.cloud.sentinel.transport.heartbeatIntervalMs\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"send heartbeat interval millisecond.\"\n    },\n    {\n      \"name\": \"spring.cloud.sentinel.filter.order\",\n      \"type\": \"java.lang.Integer\",\n      \"defaultValue\": \"Integer.MIN_VALUE\",\n      \"description\": \"SentinelWebInterceptor order, will be register to InterceptorRegistry.\"\n    },\n    {\n      \"name\": \"spring.cloud.sentinel.filter.enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": true,\n      \"description\": \"Enable to register com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor.\"\n    },\n    {\n      \"name\": \"spring.cloud.sentinel.metric.charset\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"UTF-8\",\n      \"description\": \"charset when sentinel write or search metric file.\"\n    },\n    {\n      \"name\": \"spring.cloud.sentinel.metric.fileSingleSize\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"the metric file size.\"\n    },\n    {\n      \"name\": \"spring.cloud.sentinel.metric.fileTotalCount\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"the total metric file count.\"\n    },\n    {\n      \"name\": \"spring.cloud.sentinel.log.dir\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"log base directory.\"\n    },\n    {\n      \"name\": \"spring.cloud.sentinel.log.switch-pid\",\n      \"type\": \"java.lang.Boolean\",\n      \"defaultValue\": false,\n      \"description\": \"log file should with pid.\"\n    },\n    {\n      \"name\": \"spring.cloud.sentinel.block-page\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"the process page when the flow control is triggered.\"\n    },\n    {\n      \"name\": \"spring.cloud.sentinel.servlet.block-page\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"recommend use spring.cloud.sentinel.block-page.\"\n    },\n    {\n      \"name\": \"spring.cloud.sentinel.flow.coldFactor\",\n      \"type\": \"java.lang.String\",\n      \"defaultValue\": \"3\",\n      \"description\": \"sentinel the cold factor.\"\n    },\n    {\n      \"name\": \"management.health.sentinel.enabled\",\n      \"type\": \"java.lang.Boolean\",\n      \"description\": \"Whether to enable sentinel health check.\",\n      \"defaultValue\": true\n    },\n    {\n      \"defaultValue\": \"false\",\n      \"name\": \"feign.sentinel.enabled\",\n      \"description\": \"If true, an OpenFeign client will be wrapped with a Sentinel circuit breaker.\",\n      \"type\": \"java.lang.Boolean\"\n    }\n  ]\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/resources/META-INF/native-image/reflect-config.json",
    "content": "[\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.beans.factory.support.DefaultListableBeanFactory$2\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.Entry\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.SphU\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.SphU\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.adapter.reactor.SentinelReactorTransformer\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.beans.factory.support.DefaultListableBeanFactory$2\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.adapter.spring.webmvc.AbstractSentinelInterceptor\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"afterCompletion\",\n        \"parameterTypes\": [\n          \"jakarta.servlet.http.HttpServletRequest\",\n          \"jakarta.servlet.http.HttpServletResponse\",\n          \"java.lang.Object\",\n          \"java.lang.Exception\"\n        ]\n      },\n      {\n        \"name\": \"postHandle\",\n        \"parameterTypes\": [\n          \"jakarta.servlet.http.HttpServletRequest\",\n          \"jakarta.servlet.http.HttpServletResponse\",\n          \"java.lang.Object\",\n          \"org.springframework.web.servlet.ModelAndView\"\n        ]\n      },\n      {\n        \"name\": \"preHandle\",\n        \"parameterTypes\": [\n          \"jakarta.servlet.http.HttpServletRequest\",\n          \"jakarta.servlet.http.HttpServletResponse\",\n          \"java.lang.Object\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.adapter.spring.webmvc.AbstractSentinelInterceptor\",\n    \"methods\": [\n      {\n        \"name\": \"afterCompletion\",\n        \"parameterTypes\": [\n          \"jakarta.servlet.http.HttpServletRequest\",\n          \"jakarta.servlet.http.HttpServletResponse\",\n          \"java.lang.Object\",\n          \"java.lang.Exception\"\n        ]\n      },\n      {\n        \"name\": \"postHandle\",\n        \"parameterTypes\": [\n          \"jakarta.servlet.http.HttpServletRequest\",\n          \"jakarta.servlet.http.HttpServletResponse\",\n          \"java.lang.Object\",\n          \"org.springframework.web.servlet.ModelAndView\"\n        ]\n      },\n      {\n        \"name\": \"preHandle\",\n        \"parameterTypes\": [\n          \"jakarta.servlet.http.HttpServletRequest\",\n          \"jakarta.servlet.http.HttpServletResponse\",\n          \"java.lang.Object\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.beans.factory.support.DefaultListableBeanFactory$2\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.beans.factory.support.DefaultListableBeanFactory$2\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.beans.factory.support.DefaultListableBeanFactory$2\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.beans.factory.support.DefaultListableBeanFactory$2\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.UrlCleaner\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.beans.factory.support.DefaultListableBeanFactory$2\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.adapter.spring.webmvc.config.BaseWebMvcConfig\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"getBlockExceptionHandler\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getOriginParser\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getRequestAttributeName\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"getRequestRefName\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"setBlockExceptionHandler\",\n        \"parameterTypes\": [\n          \"com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler\"\n        ]\n      },\n      {\n        \"name\": \"setOriginParser\",\n        \"parameterTypes\": [\n          \"com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser\"\n        ]\n      },\n      {\n        \"name\": \"setRequestAttributeName\",\n        \"parameterTypes\": [\n          \"java.lang.String\"\n        ]\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.beans.factory.support.DefaultListableBeanFactory$2\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.adapter.spring.webmvc.config.SentinelWebMvcConfig\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"methods\": [\n      {\n        \"name\": \"toString\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.adapter.spring.webmvc.config.SentinelWebMvcConfig\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.aspectj.weaver.patterns.ExactAnnotationTypePattern\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.annotation.SentinelResource\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.aspectj.weaver.reflect.Java15ReflectionBasedReferenceTypeDelegate\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.annotation.aspectj.AbstractSentinelAspectSupport\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.annotation.aspectj.AbstractSentinelAspectSupport\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.aspectj.internal.lang.reflect.AjTypeImpl\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.aspectj.weaver.tools.PointcutParser\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect\",\n    \"allDeclaredFields\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.aop.aspectj.annotation.AspectMetadata\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.aop.aspectj.annotation.BeanFactoryAspectInstanceFactory\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.init.InitExecutor\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.cluster.client.init.DefaultClusterClientInitFunc\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.cluster.server.TokenServiceProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.cluster.flow.DefaultTokenService\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.cluster.server.command.handler.FetchClusterFlowRulesCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.cluster.server.command.handler.FetchClusterMetricCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.cluster.server.command.handler.FetchClusterParamFlowRulesCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.cluster.server.command.handler.FetchClusterServerConfigHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.cluster.server.command.handler.FetchClusterServerInfoCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.cluster.server.command.handler.ModifyClusterFlowRulesCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.cluster.server.command.handler.ModifyClusterParamFlowRulesCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.cluster.server.command.handler.ModifyClusterServerFlowConfigHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.cluster.server.command.handler.ModifyClusterServerTransportConfigHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.cluster.server.command.handler.ModifyServerNamespaceSetHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.init.InitExecutor\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.cluster.server.init.DefaultClusterServerInitFunc\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.cluster.server.processor.RequestProcessorProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.cluster.server.processor.FlowRequestProcessor\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.cluster.server.processor.RequestProcessorProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.cluster.server.processor.ParamFlowRequestProcessor\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.ApiCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.BasicInfoCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.FetchActiveRuleCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.FetchClusterClientConfigHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.FetchClusterNodeByIdCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.FetchClusterNodeHumanCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.FetchJsonTreeCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.FetchOriginCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.FetchSimpleClusterNodeCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.FetchSystemStatusCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.FetchTreeCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.GetParamFlowRulesCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.ModifyClusterClientConfigHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.ModifyParamFlowRulesCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.ModifyRulesCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.OnOffGetCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.OnOffSetCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.SendMetricCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.VersionCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.cluster.FetchClusterModeCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandHandlerProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.command.handler.cluster.ModifyClusterModeCommandHandler\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.datasource.Converter\",\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllPublicMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.init.InitExecutor\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.init.ParamFlowStatisticSlotCallbackInit\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.init.InitExecutor\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.metric.extension.MetricCallbackInit\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.tomcat.websocket.server.WsFilter\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.slots.DefaultSlotChainBuilder\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.fasterxml.jackson.databind.deser.std.CollectionDeserializer\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.slots.block.AbstractRule\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.fasterxml.jackson.databind.deser.std.CollectionDeserializer\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.slots.block.Rule\",\n    \"queryAllDeclaredMethods\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.tomcat.websocket.server.WsFilter\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.slots.block.authority.AuthoritySlot\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.fasterxml.jackson.databind.deser.std.CollectionDeserializer\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.tomcat.websocket.server.WsFilter\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.slots.block.degrade.DegradeSlot\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.tomcat.websocket.server.WsFilter\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.slots.block.flow.FlowSlot\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.tomcat.websocket.server.WsFilter\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowSlot\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.slots.DefaultSlotChainBuilder\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.tomcat.websocket.server.WsFilter\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.tomcat.websocket.server.WsFilter\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.slots.logger.LogSlot\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.slots.DefaultSlotChainBuilder\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.slots.nodeselector.NodeSelectorSlot\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.tomcat.websocket.server.WsFilter\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.slots.nodeselector.NodeSelectorSlot\"\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.tomcat.websocket.server.WsFilter\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.slots.statistic.StatisticSlot\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"org.apache.tomcat.websocket.server.WsFilter\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.slots.system.SystemSlot\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.command.CommandCenterProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.transport.command.SimpleHttpCommandCenter\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.heartbeat.HeartbeatSenderProvider\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.transport.heartbeat.SimpleHttpHeartbeatSender\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.init.InitExecutor\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.transport.init.CommandCenterInitFunc\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"condition\": {\n      \"typeReachable\": \"com.alibaba.csp.sentinel.init.InitExecutor\"\n    },\n    \"name\": \"com.alibaba.csp.sentinel.transport.init.HeartbeatSenderInitFunc\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/resources/META-INF/native-image/resource-config.json",
    "content": "{\n  \"resources\": {\n    \"includes\": [\n    ],\n    \"excludes\": [\n      {\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.csp.sentinel.cluster.TokenService\\\\E\"\n      },\n      {\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.csp.sentinel.cluster.server.processor.RequestProcessor\\\\E\"\n      },\n      {\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.csp.sentinel.command.CommandHandler\\\\E\"\n      },\n      {\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.csp.sentinel.init.InitFunc\\\\E\"\n      },\n      {\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot\\\\E\"\n      },\n      {\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder\\\\E\"\n      },\n      {\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.csp.sentinel.transport.CommandCenter\\\\E\"\n      },\n      {\n        \"pattern\": \"\\\\QMETA-INF/services/com.alibaba.csp.sentinel.transport.HeartbeatSender\\\\E\"\n      }\n    ]\n  }\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/resources/META-INF/spring/aot.factories",
    "content": "org.springframework.aot.hint.RuntimeHintsRegistrar=\\\ncom.alibaba.cloud.sentinel.aot.hint.SentinelProtectInterceptorHints\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports",
    "content": "com.alibaba.cloud.sentinel.SentinelWebAutoConfiguration\ncom.alibaba.cloud.sentinel.SentinelWebFluxAutoConfiguration\ncom.alibaba.cloud.sentinel.endpoint.SentinelEndpointAutoConfiguration\ncom.alibaba.cloud.sentinel.custom.SentinelAutoConfiguration\ncom.alibaba.cloud.sentinel.feign.SentinelFeignAutoConfiguration\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/resources/META-INF/spring.factories",
    "content": "org.springframework.context.ApplicationContextInitializer=\\\n  com.alibaba.cloud.sentinel.custom.context.SentinelApplicationContextInitializer\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/ContextIdSentinelFeignTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel;\n\nimport com.alibaba.cloud.sentinel.feign.SentinelFeignAutoConfiguration;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.cloud.openfeign.EnableFeignClients;\nimport org.springframework.cloud.openfeign.FallbackFactory;\nimport org.springframework.cloud.openfeign.FeignClient;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.test.context.junit4.SpringRunner;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * Add this unit test to verify https://github.com/alibaba/spring-cloud-alibaba/pull/838.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@RunWith(SpringRunner.class)\n@SpringBootTest(classes = { ContextIdSentinelFeignTests.TestConfig.class },\n\t\tproperties = { \"feign.sentinel.enabled=true\" })\npublic class ContextIdSentinelFeignTests {\n\n\t@Autowired\n\tprivate EchoService echoService;\n\n\t@Autowired\n\tprivate FooService fooService;\n\n\t@Test\n\tpublic void testFeignClient() {\n\t\tassertThat(echoService.echo(\"test\")).isEqualTo(\"echo fallback\");\n\t\tassertThat(fooService.echo(\"test\")).isEqualTo(\"foo fallback\");\n\t\tassertThat(fooService.toString()).isNotEqualTo(echoService.toString());\n\t\tassertThat(fooService.hashCode()).isNotEqualTo(echoService.hashCode());\n\t\tassertThat(echoService.equals(fooService)).isEqualTo(Boolean.FALSE);\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@ImportAutoConfiguration({ SentinelFeignAutoConfiguration.class })\n\t@EnableFeignClients\n\tpublic static class TestConfig {\n\n\t}\n\n\t@FeignClient(contextId = \"echoService\", name = \"service-provider\",\n\t\t\tfallback = EchoServiceFallback.class,\n\t\t\tconfiguration = FeignConfiguration.class)\n\tpublic interface EchoService {\n\n\t\t@GetMapping(\"/echo/{str}\")\n\t\tString echo(@PathVariable(\"str\") String str);\n\n\t}\n\n\t@FeignClient(contextId = \"fooService\", value = \"foo-service\",\n\t\t\tfallbackFactory = CustomFallbackFactory.class,\n\t\t\tconfiguration = FeignConfiguration.class)\n\tpublic interface FooService {\n\n\t\t@RequestMapping(path = \"echo/{str}\")\n\t\tString echo(@RequestParam(\"str\") String param);\n\n\t}\n\n\tpublic static class FeignConfiguration {\n\n\t\t@Bean\n\t\tpublic EchoServiceFallback echoServiceFallback() {\n\t\t\treturn new EchoServiceFallback();\n\t\t}\n\n\t\t@Bean\n\t\tpublic CustomFallbackFactory customFallbackFactory() {\n\t\t\treturn new CustomFallbackFactory();\n\t\t}\n\n\t}\n\n\tpublic static class EchoServiceFallback implements EchoService {\n\n\t\t@Override\n\t\tpublic String echo(@RequestParam(\"str\") String param) {\n\t\t\treturn \"echo fallback\";\n\t\t}\n\n\t}\n\n\tpublic static class FooServiceFallback implements FooService {\n\n\t\t@Override\n\t\tpublic String echo(@RequestParam(\"str\") String param) {\n\t\t\treturn \"foo fallback\";\n\t\t}\n\n\t}\n\n\tpublic static class CustomFallbackFactory\n\t\t\timplements FallbackFactory<FooService> {\n\n\t\tprivate FooService fooService = new FooServiceFallback();\n\n\t\t@Override\n\t\tpublic FooService create(Throwable throwable) {\n\t\t\treturn fooService;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelAutoConfigurationTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel;\n\nimport java.util.Arrays;\nimport java.util.Map;\n\nimport com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;\nimport com.alibaba.cloud.sentinel.custom.SentinelAutoConfiguration;\nimport com.alibaba.cloud.sentinel.custom.SentinelBeanPostProcessor;\nimport com.alibaba.cloud.sentinel.endpoint.SentinelEndpoint;\nimport com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;\nimport com.alibaba.csp.sentinel.config.SentinelConfig;\nimport com.alibaba.csp.sentinel.log.LogBase;\nimport com.alibaba.csp.sentinel.slots.block.BlockException;\nimport com.alibaba.csp.sentinel.slots.block.RuleConstant;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;\nimport com.alibaba.csp.sentinel.transport.config.TransportConfig;\nimport com.alibaba.csp.sentinel.transport.endpoint.Endpoint;\nimport com.alibaba.csp.sentinel.transport.endpoint.Protocol;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.boot.test.web.server.LocalServerPort;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.http.HttpRequest;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.http.client.ClientHttpRequestExecution;\nimport org.springframework.http.client.ClientHttpRequestInterceptor;\nimport org.springframework.test.context.junit4.SpringRunner;\nimport org.springframework.web.client.RestClientException;\nimport org.springframework.web.client.RestTemplate;\n\nimport static com.alibaba.cloud.sentinel.SentinelConstants.BLOCK_PAGE_URL_CONF_KEY;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\nimport static org.mockito.Mockito.mock;\nimport static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n * @author jiashuai.xie\n */\n@RunWith(SpringRunner.class)\n@SpringBootTest(classes = { SentinelAutoConfigurationTests.TestConfig.class },\n\t\tproperties = { \"spring.cloud.sentinel.filter.order=123\",\n\t\t\t\t\"spring.cloud.sentinel.filter.urlPatterns=/*,/test\",\n\t\t\t\t\"spring.cloud.sentinel.metric.fileSingleSize=9999\",\n\t\t\t\t\"spring.cloud.sentinel.metric.fileTotalCount=100\",\n\t\t\t\t\"spring.cloud.sentinel.blockPage=/error\",\n\t\t\t\t\"spring.cloud.sentinel.flow.coldFactor=3\",\n\t\t\t\t\"spring.cloud.sentinel.eager=true\",\n\t\t\t\t\"spring.cloud.sentinel.log.switchPid=true\",\n\t\t\t\t\"spring.cloud.sentinel.transport.dashboard=http://localhost:8080,http://localhost:8081\",\n\t\t\t\t\"spring.cloud.sentinel.transport.port=9999\",\n\t\t\t\t\"spring.cloud.sentinel.transport.clientIp=1.1.1.1\",\n\t\t\t\t\"spring.cloud.sentinel.transport.heartbeatIntervalMs=20000\" },\n\t\twebEnvironment = RANDOM_PORT)\npublic class SentinelAutoConfigurationTests {\n\n\t@Autowired\n\tprivate SentinelProperties sentinelProperties;\n\n\t@Autowired\n\tprivate SentinelBeanPostProcessor sentinelBeanPostProcessor;\n\n\t@Autowired\n\tprivate RestTemplate restTemplate;\n\n\t@Autowired\n\tprivate RestTemplate restTemplateWithBlockClass;\n\n\t@Autowired\n\tprivate RestTemplate restTemplateWithoutBlockClass;\n\n\t@Autowired\n\tprivate RestTemplate restTemplateWithFallbackClass;\n\n\t@LocalServerPort\n\tprivate int port;\n\n\tprivate String flowUrl = \"http://localhost:\" + port + \"/flow\";\n\n\tprivate String degradeUrl = \"http://localhost:\" + port + \"/degrade\";\n\n\t@Before\n\tpublic void setUp() {\n\t\tFlowRule rule = new FlowRule();\n\t\trule.setGrade(RuleConstant.FLOW_GRADE_QPS);\n\t\trule.setCount(0);\n\t\trule.setResource(\"GET:\" + flowUrl);\n\t\trule.setLimitApp(\"default\");\n\t\trule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);\n\t\trule.setStrategy(RuleConstant.STRATEGY_DIRECT);\n\t\tFlowRuleManager.loadRules(Arrays.asList(rule));\n\t}\n\n\t@Test\n\tpublic void contextLoads() throws Exception {\n\t\tassertThat(sentinelBeanPostProcessor).isNotNull();\n\n\t\tcheckSentinelLog();\n\t\tcheckSentinelEager();\n\t\tcheckSentinelTransport();\n\t\tcheckSentinelColdFactor();\n\t\tcheckSentinelMetric();\n\t\tcheckSentinelFilter();\n\t\tcheckEndpoint();\n\t}\n\n\tprivate void checkEndpoint() {\n\t\tSentinelEndpoint sentinelEndpoint = new SentinelEndpoint(sentinelProperties);\n\t\tMap<String, Object> map = sentinelEndpoint.invoke();\n\n\t\tassertThat(map.get(\"logUsePid\")).isEqualTo(Boolean.TRUE);\n\t\tassertThat(map.get(\"consoleServer\").toString())\n\t\t\t\t.isEqualTo(Arrays\n\t\t\t\t\t\t.asList(new Endpoint(Protocol.HTTP, \"localhost\", 8080),\n\t\t\t\t\t\t\t\tnew Endpoint(Protocol.HTTP, \"localhost\", 8081))\n\t\t\t\t\t\t.toString());\n\t\tassertThat(map.get(\"clientPort\")).isEqualTo(\"9999\");\n\t\tassertThat(map.get(\"heartbeatIntervalMs\")).isEqualTo(20000L);\n\t\tassertThat(map.get(\"clientIp\")).isEqualTo(\"1.1.1.1\");\n\t\tassertThat(map.get(\"metricsFileSize\")).isEqualTo(9999L);\n\t\tassertThat(map.get(\"totalMetricsFileCount\")).isEqualTo(100);\n\t\tassertThat(map.get(\"metricsFileCharset\")).isEqualTo(\"UTF-8\");\n\t\tassertThat(map.get(\"blockPage\")).isEqualTo(\"/error\");\n\t}\n\n\tprivate void checkSentinelFilter() {\n\t\tassertThat(sentinelProperties.getFilter().getOrder()).isEqualTo(123);\n\t\tassertThat(sentinelProperties.getFilter().getUrlPatterns().size()).isEqualTo(2);\n\t\tassertThat(sentinelProperties.getFilter().getUrlPatterns().get(0))\n\t\t\t\t.isEqualTo(\"/*\");\n\t\tassertThat(sentinelProperties.getFilter().getUrlPatterns().get(1))\n\t\t\t\t.isEqualTo(\"/test\");\n\t}\n\n\tprivate void checkSentinelMetric() {\n\t\tassertThat(sentinelProperties.getMetric().getCharset()).isEqualTo(\"UTF-8\");\n\t\tassertThat(sentinelProperties.getMetric().getFileSingleSize()).isEqualTo(\"9999\");\n\t\tassertThat(sentinelProperties.getMetric().getFileTotalCount()).isEqualTo(\"100\");\n\t}\n\n\tprivate void checkSentinelColdFactor() {\n\t\tassertThat(sentinelProperties.getFlow().getColdFactor()).isEqualTo(\"3\");\n\t}\n\n\tprivate void checkSentinelTransport() {\n\t\tassertThat(sentinelProperties.getTransport().getPort()).isEqualTo(\"9999\");\n\t\tassertThat(sentinelProperties.getTransport().getDashboard())\n\t\t\t\t.isEqualTo(\"http://localhost:8080,http://localhost:8081\");\n\t\tassertThat(sentinelProperties.getTransport().getClientIp()).isEqualTo(\"1.1.1.1\");\n\t\tassertThat(sentinelProperties.getTransport().getHeartbeatIntervalMs())\n\t\t\t\t.isEqualTo(\"20000\");\n\t}\n\n\tprivate void checkSentinelEager() {\n\t\tassertThat(sentinelProperties.isEager()).isEqualTo(true);\n\t}\n\n\tprivate void checkSentinelLog() {\n\t\tassertThat(sentinelProperties.getLog().isSwitchPid()).isEqualTo(true);\n\t}\n\n\t@Test\n\tpublic void testSentinelSystemProperties() {\n\t\tassertThat(LogBase.isLogNameUsePid()).isEqualTo(true);\n\t\tassertThat(TransportConfig.getConsoleServerList().toString())\n\t\t\t\t.isEqualTo(Arrays\n\t\t\t\t\t\t.asList(new Endpoint(Protocol.HTTP, \"localhost\", 8080),\n\t\t\t\t\t\t\t\tnew Endpoint(Protocol.HTTP, \"localhost\", 8081))\n\t\t\t\t\t\t.toString());\n\t\tassertThat(TransportConfig.getPort()).isEqualTo(\"9999\");\n\t\tassertThat(TransportConfig.getHeartbeatIntervalMs().longValue())\n\t\t\t\t.isEqualTo(20000L);\n\t\tassertThat(TransportConfig.getHeartbeatClientIp()).isEqualTo(\"1.1.1.1\");\n\t\tassertThat(SentinelConfig.singleMetricFileSize()).isEqualTo(9999);\n\t\tassertThat(SentinelConfig.totalMetricFileCount()).isEqualTo(100);\n\t\tassertThat(SentinelConfig.charset()).isEqualTo(\"UTF-8\");\n\t\tassertThat(SentinelConfig.getConfig(BLOCK_PAGE_URL_CONF_KEY)).isEqualTo(\"/error\");\n\t}\n\n\t@Test\n\tpublic void testRestTemplateBlockHandler() {\n\n\t\tassertThat(restTemplate.getInterceptors().size()).isEqualTo(2);\n\t\tassertThat(restTemplateWithBlockClass.getInterceptors().size()).isEqualTo(1);\n\n\t\tResponseEntity responseEntityBlock = restTemplateWithBlockClass\n\t\t\t\t.getForEntity(flowUrl, String.class);\n\n\t\tassertThat(responseEntityBlock.getBody()).isEqualTo(\"Oops\");\n\t\tassertThat(responseEntityBlock.getStatusCode()).isEqualTo(HttpStatus.OK);\n\n\t\tResponseEntity responseEntityRaw = restTemplate.getForEntity(flowUrl,\n\t\t\t\tString.class);\n\n\t\tassertThat(responseEntityRaw.getBody())\n\t\t\t\t.isEqualTo(\"RestTemplate request block by sentinel\");\n\t\tassertThat(responseEntityRaw.getStatusCode()).isEqualTo(HttpStatus.OK);\n\t}\n\n\t@Test\n\tpublic void testNormalRestTemplate() {\n\t\tassertThat(restTemplateWithoutBlockClass.getInterceptors().size()).isEqualTo(0);\n\n\t\tassertThatThrownBy(() -> {\n\t\t\trestTemplateWithoutBlockClass.getForEntity(flowUrl, String.class);\n\t\t}).isInstanceOf(RestClientException.class);\n\t}\n\n\t@Configuration\n\tstatic class SentinelTestConfiguration {\n\n\t\t@Bean\n\t\t@SentinelRestTemplate\n\t\tRestTemplate restTemplate() {\n\t\t\tRestTemplate restTemplate = new RestTemplate();\n\t\t\trestTemplate.getInterceptors().add(mock(ClientHttpRequestInterceptor.class));\n\t\t\treturn restTemplate;\n\t\t}\n\n\t\t@Bean\n\t\t@SentinelRestTemplate(blockHandlerClass = ExceptionUtil.class,\n\t\t\t\tblockHandler = \"handleException\")\n\t\tRestTemplate restTemplateWithBlockClass() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t\t@Bean\n\t\t@SentinelRestTemplate(fallbackClass = ExceptionUtil.class,\n\t\t\t\tfallback = \"fallbackException\")\n\t\tRestTemplate restTemplateWithFallbackClass() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t\t@Bean\n\t\tRestTemplate restTemplateWithoutBlockClass() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t}\n\n\tpublic static class ExceptionUtil {\n\n\t\tpublic static SentinelClientHttpResponse handleException(HttpRequest request,\n\t\t\t\tbyte[] body, ClientHttpRequestExecution execution, BlockException ex) {\n\t\t\tSystem.out.println(\"Oops: \" + ex.getClass().getCanonicalName());\n\t\t\treturn new SentinelClientHttpResponse(\"Oops\");\n\t\t}\n\n\t\tpublic static SentinelClientHttpResponse fallbackException(HttpRequest request,\n\t\t\t\tbyte[] body, ClientHttpRequestExecution execution, BlockException ex) {\n\t\t\tSystem.out.println(\"Oops: \" + ex.getClass().getCanonicalName());\n\t\t\treturn new SentinelClientHttpResponse(\"Oops fallback\");\n\t\t}\n\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@ImportAutoConfiguration({ SentinelAutoConfiguration.class,\n\t\t\tSentinelWebAutoConfiguration.class, SentinelTestConfiguration.class })\n\tpublic static class TestConfig {\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelBeanAutowiredTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel;\n\nimport com.alibaba.cloud.sentinel.custom.SentinelAutoConfiguration;\nimport com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.BlockExceptionHandler;\nimport com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.DefaultBlockExceptionHandler;\nimport com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.RequestOriginParser;\nimport com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.config.SentinelWebMvcConfig;\nimport com.alibaba.csp.sentinel.adapter.web.common.UrlCleaner;\nimport jakarta.servlet.http.HttpServletRequest;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@RunWith(SpringRunner.class)\n@SpringBootTest(classes = { SentinelBeanAutowiredTests.TestConfig.class },\n\t\tproperties = { \"spring.cloud.sentinel.filter.order=111\" })\npublic class SentinelBeanAutowiredTests {\n\n\t@Autowired\n\tprivate UrlCleaner urlCleaner;\n\n\t@Autowired\n\tprivate BlockExceptionHandler blockExceptionHandler;\n\n\t@Autowired\n\tprivate RequestOriginParser requestOriginParser;\n\n\t@Autowired\n\tprivate SentinelProperties sentinelProperties;\n\n\t@Autowired\n\tprivate SentinelWebMvcConfig sentinelWebMvcConfig;\n\n\t@Test\n\tpublic void contextLoads() throws Exception {\n\t\tassertThat(urlCleaner).isNotNull();\n\t\tassertThat(blockExceptionHandler).isNotNull();\n\t\tassertThat(requestOriginParser).isNotNull();\n\t\tassertThat(sentinelProperties).isNotNull();\n\n\t\tcheckUrlPattern();\n\t}\n\n\tprivate void checkUrlPattern() {\n\t\tassertThat(sentinelProperties.getFilter().getOrder()).isEqualTo(111);\n\t\tassertThat(sentinelProperties.getFilter().getUrlPatterns().size()).isEqualTo(1);\n\t\tassertThat(sentinelProperties.getFilter().getUrlPatterns().get(0))\n\t\t\t\t.isEqualTo(\"/**\");\n\t}\n\n\t@Test\n\tpublic void testBeanAutowired() {\n\t\tassertThat(sentinelWebMvcConfig.getUrlCleaner()).isEqualTo(urlCleaner);\n\t\tassertThat(sentinelWebMvcConfig.getBlockExceptionHandler())\n\t\t\t\t.isEqualTo(blockExceptionHandler);\n\t\tassertThat(sentinelWebMvcConfig.getOriginParser()).isEqualTo(requestOriginParser);\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@ImportAutoConfiguration({ SentinelAutoConfiguration.class,\n\t\t\tSentinelWebAutoConfiguration.class })\n\tpublic static class TestConfig {\n\n\t\t@Bean\n\t\tpublic UrlCleaner urlCleaner() {\n\t\t\treturn new UrlCleaner() {\n\t\t\t\t@Override\n\t\t\t\tpublic String clean(String s) {\n\t\t\t\t\treturn s;\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\t@Bean\n\t\tpublic RequestOriginParser requestOriginParser() {\n\t\t\treturn new RequestOriginParser() {\n\t\t\t\t@Override\n\t\t\t\tpublic String parseOrigin(HttpServletRequest httpServletRequest) {\n\t\t\t\t\treturn httpServletRequest.getRemoteAddr();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\t@Bean\n\t\tpublic BlockExceptionHandler blockExceptionHandler() {\n\t\t\treturn new DefaultBlockExceptionHandler();\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelDataSourceTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel;\n\nimport com.alibaba.cloud.sentinel.custom.SentinelAutoConfiguration;\nimport com.alibaba.cloud.sentinel.datasource.RuleType;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@RunWith(SpringRunner.class)\n@SpringBootTest(classes = { SentinelDataSourceTests.TestConfig.class }, properties = {\n\t\t\"spring.cloud.sentinel.datasource.ds1.file.file=classpath: flowrule.json\",\n\t\t\"spring.cloud.sentinel.datasource.ds1.file.data-type=json\",\n\t\t\"spring.cloud.sentinel.datasource.ds1.file.rule-type=flow\",\n\n\t\t\"spring.cloud.sentinel.datasource.ds2.file.file=classpath: degraderule.json\",\n\t\t\"spring.cloud.sentinel.datasource.ds2.file.data-type=json\",\n\t\t\"spring.cloud.sentinel.datasource.ds2.file.rule-type=degrade\",\n\n\t\t\"spring.cloud.sentinel.datasource.ds3.file.file=classpath: authority.json\",\n\t\t\"spring.cloud.sentinel.datasource.ds3.file.rule-type=authority\",\n\n\t\t\"spring.cloud.sentinel.datasource.ds4.file.file=classpath: system.json\",\n\t\t\"spring.cloud.sentinel.datasource.ds4.file.rule-type=system\",\n\n\t\t\"spring.cloud.sentinel.datasource.ds5.file.file=classpath: param-flow.json\",\n\t\t\"spring.cloud.sentinel.datasource.ds5.file.data-type=custom\",\n\t\t\"spring.cloud.sentinel.datasource.ds5.file.converter-class=TestConverter\",\n\t\t\"spring.cloud.sentinel.datasource.ds5.file.rule-type=param-flow\" })\npublic class SentinelDataSourceTests {\n\n\t@Autowired\n\tprivate SentinelProperties sentinelProperties;\n\n\t@Test\n\tpublic void contextLoads() throws Exception {\n\t\tassertThat(sentinelProperties).isNotNull();\n\n\t\tcheckUrlPattern();\n\t}\n\n\tprivate void checkUrlPattern() {\n\t\tassertThat(sentinelProperties.getFilter().getOrder())\n\t\t\t\t.isEqualTo(Integer.MIN_VALUE);\n\t\tassertThat(sentinelProperties.getFilter().getUrlPatterns().size()).isEqualTo(1);\n\t\tassertThat(sentinelProperties.getFilter().getUrlPatterns().get(0))\n\t\t\t\t.isEqualTo(\"/**\");\n\t}\n\n\t@Test\n\tpublic void testDataSource() {\n\t\tassertThat(sentinelProperties.getDatasource().size()).isEqualTo(5);\n\t\tassertThat(sentinelProperties.getDatasource().get(\"ds1\").getApollo()).isNull();\n\t\tassertThat(sentinelProperties.getDatasource().get(\"ds1\").getNacos()).isNull();\n\t\tassertThat(sentinelProperties.getDatasource().get(\"ds1\").getZk()).isNull();\n\t\tassertThat(sentinelProperties.getDatasource().get(\"ds1\").getFile()).isNotNull();\n\n\t\tassertThat(sentinelProperties.getDatasource().get(\"ds1\").getFile().getDataType())\n\t\t\t\t.isEqualTo(\"json\");\n\t\tassertThat(sentinelProperties.getDatasource().get(\"ds1\").getFile().getRuleType())\n\t\t\t\t.isEqualTo(RuleType.FLOW);\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@ImportAutoConfiguration({ SentinelAutoConfiguration.class,\n\t\t\tSentinelWebAutoConfiguration.class })\n\tpublic static class TestConfig {\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelFallbackSupportFactoryBeanTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel;\n\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.beans.factory.FactoryBean;\nimport org.springframework.boot.autoconfigure.AutoConfigurations;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.test.context.runner.ApplicationContextRunner;\nimport org.springframework.cloud.openfeign.EnableFeignClients;\nimport org.springframework.cloud.openfeign.FeignAutoConfiguration;\nimport org.springframework.cloud.openfeign.FeignClient;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.bind.annotation.GetMapping;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author 黄学敏（huangxuemin)\n */\npublic class SentinelFallbackSupportFactoryBeanTests {\n\n\tprivate static final String FACTORY_BEAN_FALLBACK_MESSAGE = \"factoryBean fallback message\";\n\n\tprivate static final String ORIGINAL_FALLBACK_MESSAGE = \"OriginalFeign fallback message\";\n\n\tprivate final ApplicationContextRunner runner = new ApplicationContextRunner()\n\t\t\t.withBean(FactoryBeanFallbackFeignFallback.class)\n\t\t\t.withBean(OriginalFeignFallback.class)\n\t\t\t.withConfiguration(AutoConfigurations.of(TestConfiguration.class, FeignAutoConfiguration.class))\n\t\t\t.withPropertyValues(\"feign.sentinel.enabled=true\");\n\n\t@Test\n\tpublic void shouldRunFallbackFromBeanOrFactoryBean() {\n\t\trunner.run(ctx -> {\n\t\t\tassertThat(ctx.getBean(OriginalFeign.class).get()).isEqualTo(ORIGINAL_FALLBACK_MESSAGE);\n\t\t\tassertThat(ctx.getBean(FactoryBeanFallbackFeign.class).get()).isEqualTo(FACTORY_BEAN_FALLBACK_MESSAGE);\n\t\t});\n\t}\n\n\t@Configuration(proxyBeanMethods = false)\n\t@EnableFeignClients(clients = {OriginalFeign.class, FactoryBeanFallbackFeign.class })\n\t@EnableAutoConfiguration\n\tpublic static class TestConfiguration {\n\n\t}\n\n\t@FeignClient(name = \"original\", url = \"https://original\", fallback = OriginalFeignFallback.class)\n\tinterface OriginalFeign {\n\n\t\t@GetMapping(\"/\")\n\t\tString get();\n\n\t}\n\n\t@FeignClient(name = \"factoryBean\", url = \"https://factoryBean\", fallback = FactoryBeanFallbackFeignFallback.class)\n\tinterface FactoryBeanFallbackFeign {\n\n\t\t@GetMapping(\"/\")\n\t\tString get();\n\n\t}\n\n\tprivate static final class FactoryBeanFallbackFeignFallback implements FactoryBean<FactoryBeanFallbackFeign> {\n\n\t\t@Override\n\t\tpublic FactoryBeanFallbackFeign getObject() {\n\t\t\treturn () -> FACTORY_BEAN_FALLBACK_MESSAGE;\n\t\t}\n\n\t\t@Override\n\t\tpublic Class<?> getObjectType() {\n\t\t\treturn FactoryBeanFallbackFeign.class;\n\t\t}\n\n\t}\n\n\tprivate static final class OriginalFeignFallback implements OriginalFeign {\n\n\t\t@Override\n\t\tpublic String get() {\n\t\t\treturn ORIGINAL_FALLBACK_MESSAGE;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelFeignLazilyTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@RunWith(SpringRunner.class)\n@SpringBootTest(classes = {SentinelFeignTests.TestConfig.class},\n\t\tproperties = {\"feign.sentinel.enabled=true\", \"spring.cloud.openfeign.lazy-attributes-resolution=true\"})\npublic class SentinelFeignLazilyTests {\n\n\t@Autowired\n\tprivate SentinelFeignTests.EchoService echoService;\n\n\t@Autowired\n\tprivate SentinelFeignTests.FooService fooService;\n\n\t@Autowired\n\tprivate SentinelFeignTests.BarService barService;\n\n\t@Autowired\n\tprivate SentinelFeignTests.BazService bazService;\n\n\t@Test\n\tpublic void contextLoads() throws Exception {\n\t\tassertThat(echoService).isNotNull();\n\t\tassertThat(fooService).isNotNull();\n\t}\n\n\t@Test\n\tpublic void testFeignClient() {\n\t\tassertThat(echoService.echo(\"test\")).isEqualTo(\"echo fallback\");\n\t\tassertThat(fooService.echo(\"test\")).isEqualTo(\"foo fallback\");\n\n\t\tassertThatThrownBy(() -> {\n\t\t\tbarService.bar();\n\t\t}).isInstanceOf(Exception.class);\n\n\t\tassertThatThrownBy(() -> {\n\t\t\tbazService.baz();\n\t\t}).isInstanceOf(Exception.class);\n\n\t\tassertThat(fooService.toString()).isNotEqualTo(echoService.toString());\n\t\tassertThat(fooService.hashCode()).isNotEqualTo(echoService.hashCode());\n\t\tassertThat(echoService.equals(fooService)).isEqualTo(Boolean.FALSE);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelFeignTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel;\n\nimport java.util.Arrays;\n\nimport com.alibaba.cloud.sentinel.feign.SentinelFeignAutoConfiguration;\nimport com.alibaba.csp.sentinel.slots.block.RuleConstant;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.cloud.openfeign.EnableFeignClients;\nimport org.springframework.cloud.openfeign.FallbackFactory;\nimport org.springframework.cloud.openfeign.FeignClient;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.test.context.junit4.SpringRunner;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@RunWith(SpringRunner.class)\n@SpringBootTest(classes = { SentinelFeignTests.TestConfig.class },\n\t\tproperties = { \"feign.sentinel.enabled=true\" })\npublic class SentinelFeignTests {\n\n\t@Autowired\n\tprivate EchoService echoService;\n\n\t@Autowired\n\tprivate FooService fooService;\n\n\t@Autowired\n\tprivate BarService barService;\n\n\t@Autowired\n\tprivate BazService bazService;\n\n\t@Before\n\tpublic void setUp() {\n\t\tFlowRule rule1 = new FlowRule();\n\t\trule1.setGrade(RuleConstant.FLOW_GRADE_QPS);\n\t\trule1.setCount(0);\n\t\trule1.setResource(\"GET:http://test-service/echo/{str}\");\n\t\trule1.setLimitApp(\"default\");\n\t\trule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);\n\t\trule1.setStrategy(RuleConstant.STRATEGY_DIRECT);\n\t\tFlowRule rule2 = new FlowRule();\n\t\trule2.setGrade(RuleConstant.FLOW_GRADE_QPS);\n\t\trule2.setCount(0);\n\t\trule2.setResource(\"GET:http://foo-service/echo/{str}\");\n\t\trule2.setLimitApp(\"default\");\n\t\trule2.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);\n\t\trule2.setStrategy(RuleConstant.STRATEGY_DIRECT);\n\t\tFlowRule rule3 = new FlowRule();\n\t\trule3.setGrade(RuleConstant.FLOW_GRADE_QPS);\n\t\trule3.setCount(0);\n\t\trule3.setResource(\"GET:http://bar-service/bar\");\n\t\trule3.setLimitApp(\"default\");\n\t\trule3.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);\n\t\trule3.setStrategy(RuleConstant.STRATEGY_DIRECT);\n\t\tFlowRule rule4 = new FlowRule();\n\t\trule4.setGrade(RuleConstant.FLOW_GRADE_QPS);\n\t\trule4.setCount(0);\n\t\trule4.setResource(\"GET:http://baz-service/baz\");\n\t\trule4.setLimitApp(\"default\");\n\t\trule4.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);\n\t\trule4.setStrategy(RuleConstant.STRATEGY_DIRECT);\n\t\tFlowRuleManager.loadRules(Arrays.asList(rule1, rule2, rule3, rule4));\n\t}\n\n\t@Test\n\tpublic void contextLoads() throws Exception {\n\t\tassertThat(echoService).isNotNull();\n\t\tassertThat(fooService).isNotNull();\n\t}\n\n\t@Test\n\tpublic void testFeignClient() {\n\t\tassertThat(echoService.echo(\"test\")).isEqualTo(\"echo fallback\");\n\t\tassertThat(fooService.echo(\"test\")).isEqualTo(\"foo fallback\");\n\n\t\tassertThatThrownBy(() -> {\n\t\t\tbarService.bar();\n\t\t}).isInstanceOf(Exception.class);\n\n\t\tassertThatThrownBy(() -> {\n\t\t\tbazService.baz();\n\t\t}).isInstanceOf(Exception.class);\n\n\t\tassertThat(fooService.toString()).isNotEqualTo(echoService.toString());\n\t\tassertThat(fooService.hashCode()).isNotEqualTo(echoService.hashCode());\n\t\tassertThat(echoService.equals(fooService)).isEqualTo(Boolean.FALSE);\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@ImportAutoConfiguration({ SentinelFeignAutoConfiguration.class })\n\t@EnableFeignClients\n\tpublic static class TestConfig {\n\n\t\t@Bean\n\t\tpublic EchoServiceFallback echoServiceFallback() {\n\t\t\treturn new EchoServiceFallback();\n\t\t}\n\n\t\t@Bean\n\t\tpublic CustomFallbackFactory customFallbackFactory() {\n\t\t\treturn new CustomFallbackFactory();\n\t\t}\n\n\t}\n\n\t@FeignClient(value = \"test-service\", fallback = EchoServiceFallback.class)\n\tpublic interface EchoService {\n\n\t\t@RequestMapping(path = \"echo/{str}\")\n\t\tString echo(@RequestParam(\"str\") String param);\n\n\t}\n\n\t@FeignClient(value = \"foo-service\", fallbackFactory = CustomFallbackFactory.class)\n\tpublic interface FooService {\n\n\t\t@RequestMapping(path = \"echo/{str}\")\n\t\tString echo(@RequestParam(\"str\") String param);\n\n\t}\n\n\t@FeignClient(\"bar-service\")\n\tpublic interface BarService {\n\n\t\t@RequestMapping(path = \"bar\")\n\t\tString bar();\n\n\t}\n\n\tpublic interface BazService {\n\n\t\t@RequestMapping(path = \"baz\")\n\t\tString baz();\n\n\t}\n\n\t@FeignClient(\"baz-service\")\n\tpublic interface BazClient extends BazService {\n\n\t}\n\n\tpublic static class EchoServiceFallback implements EchoService {\n\n\t\t@Override\n\t\tpublic String echo(@RequestParam(\"str\") String param) {\n\t\t\treturn \"echo fallback\";\n\t\t}\n\n\t}\n\n\tpublic static class FooServiceFallback implements FooService {\n\n\t\t@Override\n\t\tpublic String echo(@RequestParam(\"str\") String param) {\n\t\t\treturn \"foo fallback\";\n\t\t}\n\n\t}\n\n\tpublic static class CustomFallbackFactory\n\t\t\timplements FallbackFactory<FooService> {\n\n\t\tprivate FooService fooService = new FooServiceFallback();\n\n\t\t@Override\n\t\tpublic FooService create(Throwable throwable) {\n\t\t\treturn fooService;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelRestTemplateTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel;\n\nimport com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;\nimport com.alibaba.cloud.sentinel.custom.SentinelBeanPostProcessor;\nimport com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;\nimport com.alibaba.csp.sentinel.slots.block.BlockException;\nimport org.junit.Test;\n\nimport org.springframework.beans.factory.BeanCreationException;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.annotation.AnnotationConfigApplicationContext;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.http.HttpRequest;\nimport org.springframework.http.client.ClientHttpRequestExecution;\nimport org.springframework.web.client.RestTemplate;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class SentinelRestTemplateTests {\n\n\t@Test(expected = BeanCreationException.class)\n\tpublic void testFbkMethod() {\n\t\tnew AnnotationConfigApplicationContext(TestConfig1.class);\n\t}\n\n\t@Test(expected = BeanCreationException.class)\n\tpublic void testFbkClass() {\n\t\tnew AnnotationConfigApplicationContext(TestConfig2.class);\n\t}\n\n\t@Test(expected = BeanCreationException.class)\n\tpublic void testblkMethod() {\n\t\tnew AnnotationConfigApplicationContext(TestConfig3.class);\n\t}\n\n\t@Test(expected = BeanCreationException.class)\n\tpublic void testblkClass() {\n\t\tnew AnnotationConfigApplicationContext(TestConfig4.class);\n\t}\n\n\t@Test\n\tpublic void testNormal() {\n\t\tAnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(\n\t\t\t\tTestConfig5.class);\n\t\tassertThat(context.getBeansOfType(RestTemplate.class).size()).isEqualTo(1);\n\t}\n\n\t@Test(expected = BeanCreationException.class)\n\tpublic void testBlkMethodExists() {\n\t\tnew AnnotationConfigApplicationContext(TestConfig6.class);\n\t}\n\n\t@Test(expected = BeanCreationException.class)\n\tpublic void testFbkMethodExists() {\n\t\tnew AnnotationConfigApplicationContext(TestConfig7.class);\n\t}\n\n\t@Test(expected = BeanCreationException.class)\n\tpublic void testBlkReturnValue() {\n\t\tnew AnnotationConfigApplicationContext(TestConfig8.class);\n\t}\n\n\t@Test(expected = BeanCreationException.class)\n\tpublic void testFbkReturnValue() {\n\t\tnew AnnotationConfigApplicationContext(TestConfig9.class);\n\t}\n\n\t@Test\n\tpublic void testNormalWithoutParam() {\n\t\tnew AnnotationConfigApplicationContext(TestConfig10.class);\n\t}\n\n\t@Test(expected = BeanCreationException.class)\n\tpublic void testUrlClnMethod() {\n\t\tnew AnnotationConfigApplicationContext(TestConfig11.class);\n\t}\n\n\t@Test(expected = BeanCreationException.class)\n\tpublic void testUrlClnClass() {\n\t\tnew AnnotationConfigApplicationContext(TestConfig12.class);\n\t}\n\n\t@Test(expected = BeanCreationException.class)\n\tpublic void testUrlClnMethodExists() {\n\t\tnew AnnotationConfigApplicationContext(TestConfig13.class);\n\t}\n\n\t@Test(expected = BeanCreationException.class)\n\tpublic void testUrlClnReturnValue() {\n\t\tnew AnnotationConfigApplicationContext(TestConfig14.class);\n\t}\n\n\t@Configuration\n\tpublic static class TestConfig1 {\n\n\t\t@Bean\n\t\tSentinelBeanPostProcessor sentinelBeanPostProcessor(\n\t\t\t\tApplicationContext applicationContext) {\n\t\t\treturn new SentinelBeanPostProcessor(applicationContext);\n\t\t}\n\n\t\t@Bean\n\t\t@SentinelRestTemplate(fallback = \"fbk\")\n\t\tRestTemplate restTemplate() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t}\n\n\t@Configuration\n\tpublic static class TestConfig2 {\n\n\t\t@Bean\n\t\tSentinelBeanPostProcessor sentinelBeanPostProcessor(\n\t\t\t\tApplicationContext applicationContext) {\n\t\t\treturn new SentinelBeanPostProcessor(applicationContext);\n\t\t}\n\n\t\t@Bean\n\t\t@SentinelRestTemplate(fallbackClass = ExceptionUtil.class)\n\t\tRestTemplate restTemplate() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t}\n\n\t@Configuration\n\tpublic static class TestConfig3 {\n\n\t\t@Bean\n\t\tSentinelBeanPostProcessor sentinelBeanPostProcessor(\n\t\t\t\tApplicationContext applicationContext) {\n\t\t\treturn new SentinelBeanPostProcessor(applicationContext);\n\t\t}\n\n\t\t@Bean\n\t\t@SentinelRestTemplate(blockHandler = \"blk\")\n\t\tRestTemplate restTemplate() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t}\n\n\t@Configuration\n\tpublic static class TestConfig4 {\n\n\t\t@Bean\n\t\tSentinelBeanPostProcessor sentinelBeanPostProcessor(\n\t\t\t\tApplicationContext applicationContext) {\n\t\t\treturn new SentinelBeanPostProcessor(applicationContext);\n\t\t}\n\n\t\t@Bean\n\t\t@SentinelRestTemplate(blockHandlerClass = ExceptionUtil.class)\n\t\tRestTemplate restTemplate() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t}\n\n\t@Configuration\n\tpublic static class TestConfig5 {\n\n\t\t@Bean\n\t\tSentinelBeanPostProcessor sentinelBeanPostProcessor(\n\t\t\t\tApplicationContext applicationContext) {\n\t\t\treturn new SentinelBeanPostProcessor(applicationContext);\n\t\t}\n\n\t\t@Bean\n\t\t@SentinelRestTemplate(\n\t\t\t\tblockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class,\n\t\t\t\tblockHandler = \"handleException\",\n\t\t\t\tfallbackClass = SentinelRestTemplateTests.ExceptionUtil.class,\n\t\t\t\tfallback = \"fallbackException\",\n\t\t\t\turlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class,\n\t\t\t\turlCleaner = \"clean\")\n\t\tRestTemplate restTemplate() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t}\n\n\t@Configuration\n\tpublic static class TestConfig6 {\n\n\t\t@Bean\n\t\tSentinelBeanPostProcessor sentinelBeanPostProcessor(\n\t\t\t\tApplicationContext applicationContext) {\n\t\t\treturn new SentinelBeanPostProcessor(applicationContext);\n\t\t}\n\n\t\t@Bean\n\t\t@SentinelRestTemplate(\n\t\t\t\tblockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class,\n\t\t\t\tblockHandler = \"handleException1\")\n\t\tRestTemplate restTemplate() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t}\n\n\t@Configuration\n\tpublic static class TestConfig7 {\n\n\t\t@Bean\n\t\tSentinelBeanPostProcessor sentinelBeanPostProcessor(\n\t\t\t\tApplicationContext applicationContext) {\n\t\t\treturn new SentinelBeanPostProcessor(applicationContext);\n\t\t}\n\n\t\t@Bean\n\t\t@SentinelRestTemplate(\n\t\t\t\tfallbackClass = SentinelRestTemplateTests.ExceptionUtil.class,\n\t\t\t\tfallback = \"fallbackException1\")\n\t\tRestTemplate restTemplate() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t}\n\n\t@Configuration\n\tpublic static class TestConfig8 {\n\n\t\t@Bean\n\t\tSentinelBeanPostProcessor sentinelBeanPostProcessor(\n\t\t\t\tApplicationContext applicationContext) {\n\t\t\treturn new SentinelBeanPostProcessor(applicationContext);\n\t\t}\n\n\t\t@Bean\n\t\t@SentinelRestTemplate(\n\t\t\t\tblockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class,\n\t\t\t\tblockHandler = \"handleException2\")\n\t\tRestTemplate restTemplate() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t}\n\n\t@Configuration\n\tpublic static class TestConfig9 {\n\n\t\t@Bean\n\t\tSentinelBeanPostProcessor sentinelBeanPostProcessor(\n\t\t\t\tApplicationContext applicationContext) {\n\t\t\treturn new SentinelBeanPostProcessor(applicationContext);\n\t\t}\n\n\t\t@Bean\n\t\t@SentinelRestTemplate(\n\t\t\t\tfallbackClass = SentinelRestTemplateTests.ExceptionUtil.class,\n\t\t\t\tfallback = \"fallbackException2\")\n\t\tRestTemplate restTemplate() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t}\n\n\t@Configuration\n\tpublic static class TestConfig10 {\n\n\t\t@Bean\n\t\tSentinelBeanPostProcessor sentinelBeanPostProcessor(\n\t\t\t\tApplicationContext applicationContext) {\n\t\t\treturn new SentinelBeanPostProcessor(applicationContext);\n\t\t}\n\n\t\t@Bean\n\t\t@SentinelRestTemplate\n\t\tRestTemplate restTemplate() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t\t@Bean\n\t\t@SentinelRestTemplate\n\t\tRestTemplate restTemplate2() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t}\n\n\t@Configuration\n\tpublic static class TestConfig11 {\n\n\t\t@Bean\n\t\tSentinelBeanPostProcessor sentinelBeanPostProcessor(\n\t\t\t\tApplicationContext applicationContext) {\n\t\t\treturn new SentinelBeanPostProcessor(applicationContext);\n\t\t}\n\n\t\t@Bean\n\t\t@SentinelRestTemplate(urlCleaner = \"cln\")\n\t\tRestTemplate restTemplate() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t}\n\n\t@Configuration\n\tpublic static class TestConfig12 {\n\n\t\t@Bean\n\t\tSentinelBeanPostProcessor sentinelBeanPostProcessor(\n\t\t\t\tApplicationContext applicationContext) {\n\t\t\treturn new SentinelBeanPostProcessor(applicationContext);\n\t\t}\n\n\t\t@Bean\n\t\t@SentinelRestTemplate(urlCleanerClass = UrlCleanUtil.class)\n\t\tRestTemplate restTemplate() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t}\n\n\t@Configuration\n\tpublic static class TestConfig13 {\n\n\t\t@Bean\n\t\tSentinelBeanPostProcessor sentinelBeanPostProcessor(\n\t\t\t\tApplicationContext applicationContext) {\n\t\t\treturn new SentinelBeanPostProcessor(applicationContext);\n\t\t}\n\n\t\t@Bean\n\t\t@SentinelRestTemplate(\n\t\t\t\turlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class,\n\t\t\t\turlCleaner = \"clean1\")\n\t\tRestTemplate restTemplate() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t}\n\n\t@Configuration\n\tpublic static class TestConfig14 {\n\n\t\t@Bean\n\t\tSentinelBeanPostProcessor sentinelBeanPostProcessor(\n\t\t\t\tApplicationContext applicationContext) {\n\t\t\treturn new SentinelBeanPostProcessor(applicationContext);\n\t\t}\n\n\t\t@Bean\n\t\t@SentinelRestTemplate(\n\t\t\t\turlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class,\n\t\t\t\turlCleaner = \"clean2\")\n\t\tRestTemplate restTemplate() {\n\t\t\treturn new RestTemplate();\n\t\t}\n\n\t}\n\n\tpublic static class ExceptionUtil {\n\n\t\tpublic static SentinelClientHttpResponse handleException(HttpRequest request,\n\t\t\t\tbyte[] body, ClientHttpRequestExecution execution, BlockException ex) {\n\t\t\tSystem.out.println(\"Oops: \" + ex.getClass().getCanonicalName());\n\t\t\treturn new SentinelClientHttpResponse(\"Oops\");\n\t\t}\n\n\t\tpublic static void handleException2(HttpRequest request, byte[] body,\n\t\t\t\tClientHttpRequestExecution execution, BlockException ex) {\n\t\t\tSystem.out.println(\"Oops: \" + ex.getClass().getCanonicalName());\n\t\t}\n\n\t\tpublic static SentinelClientHttpResponse fallbackException(HttpRequest request,\n\t\t\t\tbyte[] body, ClientHttpRequestExecution execution, BlockException ex) {\n\t\t\tSystem.out.println(\"Oops: \" + ex.getClass().getCanonicalName());\n\t\t\treturn new SentinelClientHttpResponse(\"Oops fallback\");\n\t\t}\n\n\t\tpublic static void fallbackException2(HttpRequest request, byte[] body,\n\t\t\t\tClientHttpRequestExecution execution, BlockException ex) {\n\t\t\tSystem.out.println(\"Oops: \" + ex.getClass().getCanonicalName());\n\t\t}\n\n\t}\n\n\tpublic static class UrlCleanUtil {\n\n\t\tpublic static String clean(String url) {\n\t\t\treturn url;\n\t\t}\n\n\t\tpublic static void clean2(String url) {\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/TestConverter.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel;\n\nimport java.util.List;\n\nimport com.alibaba.csp.sentinel.datasource.Converter;\nimport com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;\nimport tools.jackson.core.type.TypeReference;\nimport tools.jackson.databind.ObjectMapper;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class TestConverter implements Converter<String, List<ParamFlowRule>> {\n\n\tprivate ObjectMapper objectMapper = new ObjectMapper();\n\n\t@Override\n\tpublic List<ParamFlowRule> convert(String s) {\n\t\treturn objectMapper.readValue(s, new TypeReference<>() { });\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/aot/hint/SentinelProtectInterceptorHintsTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.aot.hint;\n\nimport java.lang.reflect.Constructor;\n\nimport com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;\nimport com.alibaba.cloud.sentinel.custom.SentinelProtectInterceptor;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.aot.hint.RuntimeHints;\nimport org.springframework.aot.hint.predicate.RuntimeHintsPredicates;\nimport org.springframework.web.client.RestTemplate;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author ruansheneg\n */\npublic class SentinelProtectInterceptorHintsTest {\n\n\t@Test\n\tpublic void shouldRegisterHints() {\n\t\tConstructor<SentinelProtectInterceptor> constructor;\n\t\ttry {\n\t\t\tconstructor = SentinelProtectInterceptor.class.getConstructor(SentinelRestTemplate.class, RestTemplate.class);\n\t\t}\n\t\tcatch (NoSuchMethodException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\tRuntimeHints hints = new RuntimeHints();\n\t\tnew SentinelProtectInterceptorHints().registerHints(hints, getClass().getClassLoader());\n\t\tassertThat(RuntimeHintsPredicates.reflection().onConstructor(constructor)).accepts(hints);\n\t}\n\n}\n\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/custom/SentinelDataSourceHandlerTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.custom;\n\nimport com.alibaba.cloud.sentinel.SentinelProperties;\nimport com.alibaba.cloud.sentinel.datasource.RuleType;\nimport com.alibaba.cloud.sentinel.datasource.config.AbstractDataSourceProperties;\nimport com.alibaba.cloud.sentinel.datasource.config.ApolloDataSourceProperties;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport org.springframework.beans.MutablePropertyValues;\nimport org.springframework.beans.factory.config.RuntimeBeanReference;\nimport org.springframework.beans.factory.support.BeanDefinitionBuilder;\nimport org.springframework.beans.factory.support.DefaultListableBeanFactory;\nimport org.springframework.core.env.Environment;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.Mockito.mock;\n\n/**\n * Test cases for {@link SentinelDataSourceHandler}.\n *\n * @author <a href=\"mailto:i@5icodes.com\">hnyyghk</a>\n */\npublic class SentinelDataSourceHandlerTests {\n\n\tprivate SentinelDataSourceHandler sentinelDataSourceHandler;\n\n\tprivate DefaultListableBeanFactory beanFactory;\n\n\tprivate SentinelProperties sentinelProperties;\n\n\tprivate Environment env;\n\n\t@Before\n\tpublic void setUp() {\n\t\tbeanFactory = mock(DefaultListableBeanFactory.class);\n\t\tsentinelProperties = mock(SentinelProperties.class);\n\t\tenv = mock(Environment.class);\n\t\tsentinelDataSourceHandler = new SentinelDataSourceHandler(beanFactory, sentinelProperties, env);\n\t}\n\n\t/**\n\t * Test cases for {@link SentinelDataSourceHandler#parseBeanDefinition(AbstractDataSourceProperties, String)}.\n\t *\n\t * @see com.alibaba.cloud.sentinel.datasource.config.ApolloDataSourceProperties\n\t * @see com.alibaba.cloud.sentinel.datasource.factorybean.ApolloDataSourceFactoryBean\n\t */\n\t@Test\n\tpublic void testParseBeanDefinition() {\n\t\tApolloDataSourceProperties dataSourceProperties = new ApolloDataSourceProperties();\n\t\tdataSourceProperties.setNamespaceName(\"application\");\n\t\tdataSourceProperties.setFlowRulesKey(\"test-flow-rules\");\n\t\tdataSourceProperties.setDefaultFlowRuleValue(\"[]\");\n\t\tdataSourceProperties.setDataType(\"json\");\n\t\tdataSourceProperties.setRuleType(RuleType.FLOW);\n\t\tString dataSourceName = \"ds1\" + \"-sentinel-\" + \"apollo\" + \"-datasource\";\n\n\t\t//init BeanDefinitionBuilder for ApolloDataSourceFactoryBean\n\t\tBeanDefinitionBuilder builder = sentinelDataSourceHandler.parseBeanDefinition(dataSourceProperties, dataSourceName);\n\t\tMutablePropertyValues propertyValues = builder.getBeanDefinition().getPropertyValues();\n\n\t\t//ApolloDataSourceFactoryBean has four parameters, $jacocoData should not be included\n\t\tassertThat(propertyValues.size()).isEqualTo(4);\n\t\tassertThat(propertyValues).noneMatch(propertyValue -> \"$jacocoData\".equals(propertyValue.getName()));\n\t\tassertThat(propertyValues).anyMatch(propertyValue -> \"flowRulesKey\".equals(propertyValue.getName())\n\t\t\t\t&& dataSourceProperties.getFlowRulesKey().equals(propertyValue.getValue()));\n\t\tassertThat(propertyValues).anyMatch(propertyValue -> \"defaultFlowRuleValue\".equals(propertyValue.getName())\n\t\t\t\t&& dataSourceProperties.getDefaultFlowRuleValue().equals(propertyValue.getValue()));\n\t\tassertThat(propertyValues).anyMatch(propertyValue -> \"namespaceName\".equals(propertyValue.getName())\n\t\t\t\t&& dataSourceProperties.getNamespaceName().equals(propertyValue.getValue()));\n\t\tassertThat(propertyValues).anyMatch(propertyValue -> \"converter\".equals(propertyValue.getName())\n\t\t\t\t&& propertyValue.getValue() instanceof RuntimeBeanReference value\n\t\t\t\t&& value.getBeanName().equals(\"sentinel-\" + dataSourceProperties.getDataType() + \"-\" + dataSourceProperties.getRuleType().getName() + \"-converter\"));\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/endpoint/SentinelHealthIndicatorTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sentinel.endpoint;\n\nimport java.lang.reflect.Field;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport com.alibaba.cloud.sentinel.SentinelProperties;\nimport com.alibaba.csp.sentinel.config.SentinelConfig;\nimport com.alibaba.csp.sentinel.datasource.AbstractDataSource;\nimport com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource;\nimport com.alibaba.csp.sentinel.heartbeat.HeartbeatSenderProvider;\nimport com.alibaba.csp.sentinel.transport.HeartbeatSender;\nimport com.alibaba.csp.sentinel.transport.config.TransportConfig;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport org.springframework.beans.factory.support.DefaultListableBeanFactory;\nimport org.springframework.boot.health.contributor.Health;\nimport org.springframework.boot.health.contributor.Status;\nimport org.springframework.util.ReflectionUtils;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\n/**\n * Test cases for {@link SentinelHealthIndicator}.\n *\n * @author cdfive\n */\npublic class SentinelHealthIndicatorTests {\n\n\tprivate SentinelHealthIndicator sentinelHealthIndicator;\n\n\tprivate DefaultListableBeanFactory beanFactory;\n\n\tprivate SentinelProperties sentinelProperties;\n\n\tprivate HeartbeatSender heartbeatSender;\n\n\t@Before\n\tpublic void setUp() {\n\t\tbeanFactory = mock(DefaultListableBeanFactory.class);\n\t\tsentinelProperties = mock(SentinelProperties.class);\n\t\tsentinelHealthIndicator = new SentinelHealthIndicator(beanFactory,\n\t\t\t\tsentinelProperties);\n\n\t\tSentinelConfig.setConfig(TransportConfig.CONSOLE_SERVER, \"\");\n\n\t\theartbeatSender = mock(HeartbeatSender.class);\n\t\tField heartbeatSenderField = ReflectionUtils\n\t\t\t\t.findField(HeartbeatSenderProvider.class, \"heartbeatSender\");\n\t\theartbeatSenderField.setAccessible(true);\n\t\tReflectionUtils.setField(heartbeatSenderField, null, heartbeatSender);\n\t}\n\n\t@Test\n\tpublic void testSentinelNotEnabled() {\n\t\twhen(sentinelProperties.isEnabled()).thenReturn(false);\n\n\t\tHealth health = sentinelHealthIndicator.health();\n\n\t\tassertThat(health.getStatus()).isEqualTo(Status.UP);\n\t\tassertThat(health.getDetails().get(\"enabled\")).isEqualTo(false);\n\t}\n\n\t@Test\n\tpublic void testSentinelDashboardNotConfigured() {\n\t\twhen(sentinelProperties.isEnabled()).thenReturn(true);\n\n\t\tHealth health = sentinelHealthIndicator.health();\n\n\t\tassertThat(health.getStatus()).isEqualTo(Status.UP);\n\t\tassertThat(health.getDetails().get(\"dashboard\")).isEqualTo(Status.UNKNOWN);\n\t}\n\n\t@Test\n\tpublic void testSentinelDashboardConfiguredSuccess() throws Exception {\n\t\twhen(sentinelProperties.isEnabled()).thenReturn(true);\n\t\tSentinelConfig.setConfig(TransportConfig.CONSOLE_SERVER, \"localhost:8080\");\n\t\twhen(heartbeatSender.sendHeartbeat()).thenReturn(true);\n\n\t\tHealth health = sentinelHealthIndicator.health();\n\n\t\tassertThat(health.getStatus()).isEqualTo(Status.UP);\n\t}\n\n\t@Test\n\tpublic void testSentinelDashboardConfiguredFailed() throws Exception {\n\t\twhen(sentinelProperties.isEnabled()).thenReturn(true);\n\t\tSentinelConfig.setConfig(TransportConfig.CONSOLE_SERVER, \"localhost:8080\");\n\t\twhen(heartbeatSender.sendHeartbeat()).thenReturn(false);\n\n\t\tHealth health = sentinelHealthIndicator.health();\n\n\t\tassertThat(health.getStatus()).isEqualTo(Status.UNKNOWN);\n\t\tassertThat(health.getDetails().get(\"dashboard\")).isEqualTo(new Status(\n\t\t\t\tStatus.UNKNOWN.getCode(), \"localhost:8080 can't be connected\"));\n\t}\n\n\t@Test\n\tpublic void testSentinelDataSourceSuccess() throws Exception {\n\t\twhen(sentinelProperties.isEnabled()).thenReturn(true);\n\t\tSentinelConfig.setConfig(TransportConfig.CONSOLE_SERVER, \"localhost:8080\");\n\t\twhen(heartbeatSender.sendHeartbeat()).thenReturn(true);\n\n\t\tMap<String, AbstractDataSource> dataSourceMap = new HashMap<>();\n\n\t\tFileRefreshableDataSource fileDataSource1 = mock(FileRefreshableDataSource.class);\n\t\tdataSourceMap.put(\"ds1-sentinel-file-datasource\", fileDataSource1);\n\n\t\tFileRefreshableDataSource fileDataSource2 = mock(FileRefreshableDataSource.class);\n\t\tdataSourceMap.put(\"ds2-sentinel-file-datasource\", fileDataSource2);\n\n\t\twhen(beanFactory.getBeansOfType(AbstractDataSource.class))\n\t\t\t\t.thenReturn(dataSourceMap);\n\n\t\tHealth health = sentinelHealthIndicator.health();\n\n\t\tassertThat(health.getStatus()).isEqualTo(Status.UP);\n\t\tMap<String, Status> dataSourceDetailMap = (Map<String, Status>) health\n\t\t\t\t.getDetails().get(\"dataSource\");\n\t\tassertThat(dataSourceDetailMap.get(\"ds1-sentinel-file-datasource\"))\n\t\t\t\t.isEqualTo(Status.UP);\n\t\tassertThat(dataSourceDetailMap.get(\"ds2-sentinel-file-datasource\"))\n\t\t\t\t.isEqualTo(Status.UP);\n\t}\n\n\t@Test\n\tpublic void testSentinelDataSourceFailed() throws Exception {\n\t\twhen(sentinelProperties.isEnabled()).thenReturn(true);\n\t\tSentinelConfig.setConfig(TransportConfig.CONSOLE_SERVER, \"localhost:8080\");\n\t\twhen(heartbeatSender.sendHeartbeat()).thenReturn(true);\n\n\t\tMap<String, AbstractDataSource> dataSourceMap = new HashMap<>();\n\n\t\tFileRefreshableDataSource fileDataSource1 = mock(FileRefreshableDataSource.class);\n\t\tdataSourceMap.put(\"ds1-sentinel-file-datasource\", fileDataSource1);\n\n\t\tFileRefreshableDataSource fileDataSource2 = mock(FileRefreshableDataSource.class);\n\t\twhen(fileDataSource2.loadConfig())\n\t\t\t\t.thenThrow(new RuntimeException(\"fileDataSource2 error\"));\n\t\tdataSourceMap.put(\"ds2-sentinel-file-datasource\", fileDataSource2);\n\n\t\twhen(beanFactory.getBeansOfType(AbstractDataSource.class))\n\t\t\t\t.thenReturn(dataSourceMap);\n\n\t\tHealth health = sentinelHealthIndicator.health();\n\n\t\tassertThat(health.getStatus()).isEqualTo(Status.UNKNOWN);\n\t\tMap<String, Status> dataSourceDetailMap = (Map<String, Status>) health\n\t\t\t\t.getDetails().get(\"dataSource\");\n\t\tassertThat(dataSourceDetailMap.get(\"ds1-sentinel-file-datasource\"))\n\t\t\t\t.isEqualTo(Status.UP);\n\t\tassertThat(dataSourceDetailMap.get(\"ds2-sentinel-file-datasource\"))\n\t\t\t\t.isEqualTo(new Status(Status.UNKNOWN.getCode(), \"fileDataSource2 error\"));\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/resources/authority.json",
    "content": "[\n  {\n    \"resource\": \"good\",\n    \"limitApp\": \"abc\",\n    \"strategy\": 0\n  },\n  {\n    \"resource\": \"bad\",\n    \"limitApp\": \"bcd\",\n    \"strategy\": 1\n  },\n  {\n    \"resource\": \"terrible\",\n    \"limitApp\": \"aaa\",\n    \"strategy\": 1\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/resources/degraderule.json",
    "content": "[\n  {\n    \"resource\": \"abc0\",\n    \"count\": 20.0,\n    \"grade\": 0,\n    \"passCount\": 0,\n    \"timeWindow\": 10\n  },\n  {\n    \"resource\": \"abc1\",\n    \"count\": 15.0,\n    \"grade\": 0,\n    \"passCount\": 0,\n    \"timeWindow\": 10\n  }\n]"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/resources/flowrule.json",
    "content": "[\n  {\n    \"resource\": \"resource\",\n    \"controlBehavior\": 0,\n    \"count\": 1,\n    \"grade\": 1,\n    \"limitApp\": \"default\",\n    \"strategy\": 0\n  },\n  {\n    \"resource\": \"p\",\n    \"controlBehavior\": 0,\n    \"count\": 1,\n    \"grade\": 1,\n    \"limitApp\": \"default\",\n    \"strategy\": 0\n  },\n  {\n    \"resource\": \"http://www.taobao.com\",\n    \"controlBehavior\": 0,\n    \"count\": 0,\n    \"grade\": 1,\n    \"limitApp\": \"default\",\n    \"strategy\": 0\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/resources/param-flow.json",
    "content": "[\n  {\n    \"resource\": \"hotResource\",\n    \"count\": 0,\n    \"grade\": 1,\n    \"limitApp\": \"default\",\n    \"paramIdx\": 0,\n    \"paramFlowItemList\": [\n      {\n        \"object\": \"2\",\n        \"classType\": \"int\",\n        \"count\": 1\n      }\n    ]\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/resources/system.json",
    "content": "[\n  {\n    \"highestSystemLoad\": -1,\n    \"qps\": 100,\n    \"avgRt\": -1,\n    \"maxThread\": 10\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-starters</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>\n    <name>Spring Cloud Starter Alibaba Sidecar</name>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-gateway-server-webflux</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-consul-discovery</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-configuration-processor</artifactId>\n            <optional>true</optional>\n        </dependency>\n    </dependencies>\n</project>"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/CustomHealthCheckHandler.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sidecar;\n\n/**\n * @author yuhuangbin\n */\npublic interface CustomHealthCheckHandler {\n\n\tvoid handler(String applicationName, SidecarInstanceInfo sidecarInstanceInfo);\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sidecar;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.env.ConfigurableEnvironment;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author www.itmuch.com\n */\n@Configuration(proxyBeanMethods = false)\npublic class SidecarAutoConfiguration {\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\tpublic RestTemplate restTemplate() {\n\t\treturn new RestTemplate();\n\t}\n\n\t@Bean\n\t@ConditionalOnEnabledHealthIndicator(\"sidecar\")\n\tpublic SidecarHealthIndicator sidecarHealthIndicator(\n\t\t\tSidecarProperties sidecarProperties, RestTemplate restTemplate) {\n\t\treturn new SidecarHealthIndicator(sidecarProperties, restTemplate);\n\t}\n\n\t@Bean\n\tpublic SidecarHealthChecker sidecarHealthChecker(\n\t\t\tSidecarDiscoveryClient sidecarDiscoveryClient,\n\t\t\tSidecarHealthIndicator sidecarHealthIndicator,\n\t\t\tSidecarProperties sidecarProperties, ConfigurableEnvironment environment) {\n\t\tSidecarHealthChecker cleaner = new SidecarHealthChecker(sidecarDiscoveryClient,\n\t\t\t\tsidecarHealthIndicator, sidecarProperties, environment);\n\t\tcleaner.check();\n\t\treturn cleaner;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarDiscoveryClient.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sidecar;\n\n/**\n * @author www.itmuch.com\n */\npublic interface SidecarDiscoveryClient {\n\n\t/**\n\t * register instance.\n\t * @param applicationName applicationName\n\t * @param ip ip\n\t * @param port port\n\t */\n\tvoid registerInstance(String applicationName, String ip, Integer port);\n\n\t/**\n\t * deregister instance.\n\t * @param applicationName applicationName\n\t * @param ip ip\n\t * @param port port\n\t */\n\tvoid deregisterInstance(String applicationName, String ip, Integer port);\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarHealthChecker.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sidecar;\n\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.TimeUnit;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport reactor.core.scheduler.Schedulers;\n\nimport org.springframework.beans.factory.ObjectProvider;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.health.contributor.HealthIndicator;\nimport org.springframework.boot.health.contributor.Status;\nimport org.springframework.core.env.ConfigurableEnvironment;\n\n/**\n * @author www.itmuch.com\n * @author yuhuangbin\n */\npublic class SidecarHealthChecker {\n\n\tprivate static final Logger log = LoggerFactory.getLogger(SidecarHealthChecker.class);\n\n\tprivate final Map<String, SidecarInstanceInfo> sidecarInstanceCacheMap = new ConcurrentHashMap<>();\n\n\tprivate final SidecarDiscoveryClient sidecarDiscoveryClient;\n\n\tprivate final HealthIndicator healthIndicator;\n\n\tprivate final SidecarProperties sidecarProperties;\n\n\tprivate final ConfigurableEnvironment environment;\n\n\t@Autowired\n\tprivate ObjectProvider<CustomHealthCheckHandler> customHealthCheckHandlerObjectProvider;\n\n\tpublic SidecarHealthChecker(SidecarDiscoveryClient sidecarDiscoveryClient,\n\t\t\tHealthIndicator healthIndicator, SidecarProperties sidecarProperties,\n\t\t\tConfigurableEnvironment environment) {\n\t\tthis.sidecarDiscoveryClient = sidecarDiscoveryClient;\n\t\tthis.healthIndicator = healthIndicator;\n\t\tthis.sidecarProperties = sidecarProperties;\n\t\tthis.environment = environment;\n\t}\n\n\tpublic void check() {\n\t\tSchedulers.single().schedulePeriodically(() -> {\n\t\t\tString applicationName = environment.getProperty(\"spring.application.name\");\n\t\t\tString ip = sidecarProperties.getIp();\n\t\t\tInteger port = sidecarProperties.getPort();\n\n\t\t\tStatus status = healthIndicator.health().getStatus();\n\n\t\t\tSidecarInstanceInfo sidecarInstanceInfo = instanceCache(applicationName, ip,\n\t\t\t\t\tport, status);\n\t\t\tif (status.equals(Status.UP)) {\n\t\t\t\tif (needRegister(applicationName, sidecarInstanceInfo)) {\n\t\t\t\t\tthis.sidecarDiscoveryClient.registerInstance(applicationName, ip,\n\t\t\t\t\t\t\tport);\n\t\t\t\t\tlog.info(\n\t\t\t\t\t\t\t\"Polyglot service changed and Health check success. register the new instance. applicationName = {}, ip = {}, port = {}, status = {}\",\n\t\t\t\t\t\t\tapplicationName, ip, port, status);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlog.warn(\n\t\t\t\t\t\t\"Health check failed. unregister this instance. applicationName = {}, ip = {}, port = {}, status = {}\",\n\t\t\t\t\t\tapplicationName, ip, port, status);\n\t\t\t\tthis.sidecarDiscoveryClient.deregisterInstance(applicationName, ip, port);\n\n\t\t\t\tsidecarInstanceCacheMap.put(applicationName,\n\t\t\t\t\t\tbuildCache(ip, port, status));\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tcustomHealthCheckHandlerObjectProvider\n\t\t\t\t\t\t.ifAvailable(customHealthCheckHandler -> customHealthCheckHandler\n\t\t\t\t\t\t\t\t.handler(applicationName, sidecarInstanceInfo));\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\t\t\t\t// ignore\n\t\t\t}\n\t\t}, 0, sidecarProperties.getHealthCheckInterval(), TimeUnit.MILLISECONDS);\n\t}\n\n\tprivate SidecarInstanceInfo instanceCache(String applicationName, String ip,\n\t\t\tInteger port, Status status) {\n\t\tSidecarInstanceInfo sidecarInstanceInfo = buildCache(ip, port, status);\n\t\tsidecarInstanceCacheMap.putIfAbsent(applicationName, sidecarInstanceInfo);\n\t\treturn sidecarInstanceInfo;\n\t}\n\n\tprivate boolean needRegister(String applicationName,\n\t\t\tSidecarInstanceInfo sidecarInstanceInfo) {\n\t\tSidecarInstanceInfo cacheRecord = sidecarInstanceCacheMap.get(applicationName);\n\t\tif (!Objects.equals(sidecarInstanceInfo, cacheRecord)) {\n\t\t\t// modify the cache info\n\t\t\tsidecarInstanceCacheMap.put(applicationName, sidecarInstanceInfo);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate SidecarInstanceInfo buildCache(String ip, Integer port, Status status) {\n\t\tSidecarInstanceInfo cache = new SidecarInstanceInfo();\n\t\tcache.setIp(ip);\n\t\tcache.setPort(port);\n\t\tcache.setStatus(status);\n\t\treturn cache;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarHealthIndicator.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sidecar;\n\nimport java.net.URI;\nimport java.util.Map;\n\nimport org.springframework.boot.health.contributor.AbstractHealthIndicator;\nimport org.springframework.boot.health.contributor.Health;\nimport org.springframework.core.ParameterizedTypeReference;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author www.itmuch.com\n */\npublic class SidecarHealthIndicator extends AbstractHealthIndicator {\n\n\tprivate final SidecarProperties sidecarProperties;\n\n\tprivate final RestTemplate restTemplate;\n\n\tpublic SidecarHealthIndicator(SidecarProperties sidecarProperties,\n\t\t\tRestTemplate restTemplate) {\n\t\tthis.sidecarProperties = sidecarProperties;\n\t\tthis.restTemplate = restTemplate;\n\t}\n\n\t@Override\n\tprotected void doHealthCheck(Health.Builder builder) throws Exception {\n\t\ttry {\n\t\t\tURI uri = this.sidecarProperties.getHealthCheckUrl();\n\t\t\tif (uri == null) {\n\t\t\t\tbuilder.up();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tResponseEntity<Map<String, Object>> exchange = this.restTemplate.exchange(uri,\n\t\t\t\t\tHttpMethod.GET, null,\n\t\t\t\t\tnew ParameterizedTypeReference<Map<String, Object>>() {\n\t\t\t\t\t});\n\n\t\t\tMap<String, Object> map = exchange.getBody();\n\n\t\t\tif (map == null) {\n\t\t\t\tthis.getWarning(builder);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tObject status = map.get(\"status\");\n\t\t\tif (status instanceof String strStatus) {\n\t\t\t\tbuilder.status(strStatus);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.getWarning(builder);\n\t\t\t}\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tbuilder.down().withDetail(\"error\", e.getMessage());\n\t\t}\n\t}\n\n\tprivate void getWarning(Health.Builder builder) {\n\t\tbuilder.unknown().withDetail(\"warning\", \"no status field in response\");\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarInstanceInfo.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sidecar;\n\nimport java.util.Objects;\n\nimport org.springframework.boot.health.contributor.Status;\n\n/**\n * @author yuhuangbin\n */\npublic class SidecarInstanceInfo {\n\n\tprivate String ip;\n\n\tprivate Integer port;\n\n\tprivate Status status;\n\n\tpublic String getIp() {\n\t\treturn ip;\n\t}\n\n\tpublic void setIp(String ip) {\n\t\tthis.ip = ip;\n\t}\n\n\tpublic Integer getPort() {\n\t\treturn port;\n\t}\n\n\tpublic void setPort(Integer port) {\n\t\tthis.port = port;\n\t}\n\n\tpublic Status getStatus() {\n\t\treturn status;\n\t}\n\n\tpublic void setStatus(Status status) {\n\t\tthis.status = status;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (this == o) {\n\t\t\treturn true;\n\t\t}\n\t\tif (o == null || getClass() != o.getClass()) {\n\t\t\treturn false;\n\t\t}\n\t\tSidecarInstanceInfo that = (SidecarInstanceInfo) o;\n\t\treturn Objects.equals(ip, that.ip) && Objects.equals(port, that.port)\n\t\t\t\t&& Objects.equals(status, that.status);\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn Objects.hash(ip, port, status);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sidecar;\n\nimport java.net.URI;\n\nimport jakarta.validation.constraints.Max;\nimport jakarta.validation.constraints.Min;\nimport jakarta.validation.constraints.NotNull;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.validation.annotation.Validated;\n\n/**\n * @author www.itmuch.com\n */\n@ConfigurationProperties(\"sidecar\")\n@Validated\npublic class SidecarProperties {\n\n\t/**\n\t * polyglot service's ip.\n\t */\n\tprivate String ip;\n\n\t/**\n\t * polyglot service's port.\n\t */\n\t@NotNull\n\t@Max(65535)\n\t@Min(1)\n\tprivate Integer port;\n\n\t/**\n\t * polyglot service's health check url. this endpoint must return json and the format\n\t * must follow spring boot actuator's health endpoint. eg. {\"status\": \"UP\"}.\n\t */\n\tprivate URI healthCheckUrl;\n\n\t/**\n\t * interval of health check.\n\t */\n\tprivate long healthCheckInterval = 30000L;\n\n\tpublic String getIp() {\n\t\treturn ip;\n\t}\n\n\tpublic void setIp(String ip) {\n\t\tthis.ip = ip;\n\t}\n\n\tpublic Integer getPort() {\n\t\treturn port;\n\t}\n\n\tpublic void setPort(Integer port) {\n\t\tthis.port = port;\n\t}\n\n\tpublic URI getHealthCheckUrl() {\n\t\treturn healthCheckUrl;\n\t}\n\n\tpublic void setHealthCheckUrl(URI healthCheckUrl) {\n\t\tthis.healthCheckUrl = healthCheckUrl;\n\t}\n\n\tpublic long getHealthCheckInterval() {\n\t\treturn healthCheckInterval;\n\t}\n\n\tpublic void setHealthCheckInterval(long healthCheckInterval) {\n\t\tthis.healthCheckInterval = healthCheckInterval;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/consul/SidecarConsulAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sidecar.consul;\n\nimport java.util.List;\n\nimport com.alibaba.cloud.sidecar.SidecarAutoConfiguration;\nimport com.alibaba.cloud.sidecar.SidecarDiscoveryClient;\nimport com.alibaba.cloud.sidecar.SidecarProperties;\n\nimport org.springframework.beans.factory.ObjectProvider;\nimport org.springframework.boot.autoconfigure.AutoConfigureBefore;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;\nimport org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;\nimport org.springframework.cloud.consul.discovery.HeartbeatProperties;\nimport org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration;\nimport org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistrationAutoConfiguration;\nimport org.springframework.cloud.consul.serviceregistry.ConsulManagementRegistrationCustomizer;\nimport org.springframework.cloud.consul.serviceregistry.ConsulRegistrationCustomizer;\nimport org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry;\nimport org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistryAutoConfiguration;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author www.itmuch.com\n */\n@Configuration(proxyBeanMethods = false)\n@ConditionalOnClass(ConsulServiceRegistryAutoConfiguration.class)\n@AutoConfigureBefore({ ConsulAutoServiceRegistrationAutoConfiguration.class,\n\t\tSidecarAutoConfiguration.class })\npublic class SidecarConsulAutoConfiguration {\n\n\t@Bean\n\tpublic ConsulAutoRegistration consulRegistration(\n\t\t\tAutoServiceRegistrationProperties autoServiceRegistrationProperties,\n\t\t\tConsulDiscoveryProperties properties, ApplicationContext applicationContext,\n\t\t\tObjectProvider<List<ConsulRegistrationCustomizer>> registrationCustomizers,\n\t\t\tObjectProvider<List<ConsulManagementRegistrationCustomizer>> managementRegistrationCustomizers,\n\t\t\tHeartbeatProperties heartbeatProperties,\n\t\t\tSidecarProperties sidecarProperties) {\n\t\treturn SidecarConsulAutoRegistration.registration(\n\t\t\t\tautoServiceRegistrationProperties, properties, applicationContext,\n\t\t\t\tregistrationCustomizers.getIfAvailable(),\n\t\t\t\tmanagementRegistrationCustomizers.getIfAvailable(), heartbeatProperties,\n\t\t\t\tsidecarProperties);\n\t}\n\n\t@Bean\n\tpublic SidecarDiscoveryClient sidecarDiscoveryClient(\n\t\t\tConsulDiscoveryProperties properties, ConsulServiceRegistry serviceRegistry,\n\t\t\tConsulAutoRegistration registration) {\n\t\treturn new SidecarConsulDiscoveryClient(properties, serviceRegistry,\n\t\t\t\tregistration);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/consul/SidecarConsulAutoRegistration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sidecar.consul;\n\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.alibaba.cloud.sidecar.SidecarProperties;\n\nimport org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;\nimport org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;\nimport org.springframework.cloud.consul.discovery.HeartbeatProperties;\nimport org.springframework.cloud.consul.model.http.agent.NewService;\nimport org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration;\nimport org.springframework.cloud.consul.serviceregistry.ConsulManagementRegistrationCustomizer;\nimport org.springframework.cloud.consul.serviceregistry.ConsulRegistrationCustomizer;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.core.env.Environment;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.util.StringUtils;\n\n/**\n * @author www.itmuch.com\n */\npublic class SidecarConsulAutoRegistration extends ConsulAutoRegistration {\n\n\tpublic SidecarConsulAutoRegistration(NewService service,\n\t\t\tAutoServiceRegistrationProperties autoServiceRegistrationProperties,\n\t\t\tConsulDiscoveryProperties properties, ApplicationContext context,\n\t\t\tHeartbeatProperties heartbeatProperties,\n\t\t\tList<ConsulManagementRegistrationCustomizer> managementRegistrationCustomizers) {\n\t\tsuper(service, autoServiceRegistrationProperties, properties, context,\n\t\t\t\theartbeatProperties, managementRegistrationCustomizers);\n\t}\n\n\tpublic static ConsulAutoRegistration registration(\n\t\t\tAutoServiceRegistrationProperties autoServiceRegistrationProperties,\n\t\t\tConsulDiscoveryProperties properties, ApplicationContext context,\n\t\t\tList<ConsulRegistrationCustomizer> registrationCustomizers,\n\t\t\tList<ConsulManagementRegistrationCustomizer> managementRegistrationCustomizers,\n\t\t\tHeartbeatProperties heartbeatProperties,\n\t\t\tSidecarProperties sidecarProperties) {\n\n\t\tNewService service = new NewService();\n\t\tString appName = getAppName(properties, context.getEnvironment());\n\t\tservice.setId(getInstanceId(sidecarProperties, context.getEnvironment()));\n\t\tif (!properties.isPreferAgentAddress()) {\n\t\t\tservice.setAddress(sidecarProperties.getIp());\n\t\t}\n\t\tservice.setName(normalizeForDns(appName));\n\t\tservice.setTags(new ArrayList<>(properties.getTags()));\n\t\tservice.setEnableTagOverride(properties.getEnableTagOverride());\n\t\tservice.setMeta(getMetadata(properties));\n\n\t\tif (sidecarProperties.getPort() != null && sidecarProperties.getPort() > 0) {\n\t\t\tservice.setPort(properties.getPort());\n\t\t}\n\t\telse if (properties.getPort() != null && properties.getPort() > 0) {\n\t\t\tservice.setPort(properties.getPort());\n\t\t}\n\t\telse if (context.getEnvironment().getProperty(\"server.port\") != null) {\n\t\t\t// set health check, use alibaba sidecar self's port rather than polyglot\n\t\t\t// app's port.\n\t\t\tservice.setPort(\n\t\t\t\t\tInteger.valueOf(context.getEnvironment().getProperty(\"server.port\")));\n\t\t}\n\n\t\tif (service.getPort() != null) {\n\t\t\t// we know the port and can set the check\n\t\t\tsetCheck(service, autoServiceRegistrationProperties, properties, context,\n\t\t\t\t\theartbeatProperties);\n\t\t}\n\n\t\tConsulAutoRegistration registration = new ConsulAutoRegistration(service,\n\t\t\t\tautoServiceRegistrationProperties, properties, context,\n\t\t\t\theartbeatProperties, managementRegistrationCustomizers);\n\t\tcustomize(registrationCustomizers, registration);\n\t\treturn registration;\n\t}\n\n\t/**\n\t * copyed from\n\t * org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration#getMetadata.\n\t */\n\tprivate static Map<String, String> getMetadata(ConsulDiscoveryProperties properties) {\n\t\tLinkedHashMap<String, String> metadata = new LinkedHashMap<>();\n\t\tif (!CollectionUtils.isEmpty(properties.getMetadata())) {\n\t\t\tmetadata.putAll(properties.getMetadata());\n\t\t}\n\n\t\t// add metadata from other properties. See createTags above.\n\t\tif (StringUtils.hasLength(properties.getInstanceZone())) {\n\t\t\tmetadata.put(properties.getDefaultZoneMetadataName(),\n\t\t\t\t\tproperties.getInstanceZone());\n\t\t}\n\t\tif (StringUtils.hasLength(properties.getInstanceGroup())) {\n\t\t\tmetadata.put(\"group\", properties.getInstanceGroup());\n\t\t}\n\n\t\t// store the secure flag in the tags so that clients will be able to figure\n\t\t// out whether to use http or https automatically\n\t\tmetadata.put(\"secure\",\n\t\t\t\tBoolean.toString(properties.getScheme().equalsIgnoreCase(\"https\")));\n\n\t\treturn metadata;\n\t}\n\n\tpublic static String getInstanceId(SidecarProperties sidecarProperties,\n\t\t\tEnvironment environment) {\n\t\treturn String.format(\"%s-%s-%s\",\n\t\t\t\tenvironment.getProperty(\"spring.application.name\"),\n\t\t\t\tsidecarProperties.getIp(), sidecarProperties.getPort());\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/consul/SidecarConsulDiscoveryClient.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sidecar.consul;\n\nimport com.alibaba.cloud.sidecar.SidecarDiscoveryClient;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;\nimport org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration;\nimport org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry;\n\n/**\n * @author www.itmuch.com\n */\npublic class SidecarConsulDiscoveryClient implements SidecarDiscoveryClient {\n\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(SidecarConsulDiscoveryClient.class);\n\n\tprivate final ConsulDiscoveryProperties properties;\n\n\tprivate final ConsulServiceRegistry serviceRegistry;\n\n\tprivate final ConsulAutoRegistration registration;\n\n\tpublic SidecarConsulDiscoveryClient(ConsulDiscoveryProperties properties,\n\t\t\tConsulServiceRegistry serviceRegistry, ConsulAutoRegistration registration) {\n\t\tthis.properties = properties;\n\t\tthis.serviceRegistry = serviceRegistry;\n\t\tthis.registration = registration;\n\t}\n\n\t@Override\n\tpublic void registerInstance(String applicationName, String ip, Integer port) {\n\n\t\tif (!this.properties.isRegister()) {\n\t\t\tlog.debug(\"Registration disabled.\");\n\t\t\treturn;\n\t\t}\n\n\t\tserviceRegistry.register(registration);\n\n\t}\n\n\t@Override\n\tpublic void deregisterInstance(String applicationName, String ip, Integer port) {\n\t\tif (!this.properties.isRegister() || !this.properties.isDeregister()) {\n\t\t\treturn;\n\t\t}\n\t\tserviceRegistry.deregister(registration);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/nacos/SidecarNacosAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sidecar.nacos;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.nacos.NacosServiceManager;\nimport com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration;\nimport com.alibaba.cloud.sidecar.SidecarAutoConfiguration;\nimport com.alibaba.cloud.sidecar.SidecarDiscoveryClient;\nimport com.alibaba.cloud.sidecar.SidecarProperties;\n\nimport org.springframework.boot.autoconfigure.AutoConfigureBefore;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author www.itmuch.com\n */\n@Configuration(proxyBeanMethods = false)\n@AutoConfigureBefore({ NacosDiscoveryAutoConfiguration.class,\n\t\tSidecarAutoConfiguration.class })\n@ConditionalOnClass(NacosDiscoveryProperties.class)\n@EnableConfigurationProperties(SidecarProperties.class)\npublic class SidecarNacosAutoConfiguration {\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\tpublic SidecarNacosDiscoveryProperties sidecarNacosDiscoveryProperties(\n\t\t\tSidecarProperties sidecarProperties) {\n\t\treturn new SidecarNacosDiscoveryProperties(sidecarProperties);\n\t}\n\n\t@Bean\n\t@ConditionalOnMissingBean\n\tpublic SidecarDiscoveryClient sidecarDiscoveryClient(\n\t\t\tNacosServiceManager nacosServiceManager,\n\t\t\tSidecarNacosDiscoveryProperties sidecarNacosDiscoveryProperties) {\n\t\treturn new SidecarNacosDiscoveryClient(nacosServiceManager,\n\t\t\t\tsidecarNacosDiscoveryProperties);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/nacos/SidecarNacosDiscoveryClient.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sidecar.nacos;\n\nimport com.alibaba.cloud.nacos.NacosServiceManager;\nimport com.alibaba.cloud.sidecar.SidecarDiscoveryClient;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.NamingService;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * @author www.itmuch.com\n */\npublic class SidecarNacosDiscoveryClient implements SidecarDiscoveryClient {\n\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(SidecarNacosDiscoveryClient.class);\n\n\tprivate NacosServiceManager nacosServiceManager;\n\n\tprivate final SidecarNacosDiscoveryProperties sidecarNacosDiscoveryProperties;\n\n\tpublic SidecarNacosDiscoveryClient(NacosServiceManager nacosServiceManager,\n\t\t\tSidecarNacosDiscoveryProperties sidecarNacosDiscoveryProperties) {\n\t\tthis.nacosServiceManager = nacosServiceManager;\n\t\tthis.sidecarNacosDiscoveryProperties = sidecarNacosDiscoveryProperties;\n\t}\n\n\t@Override\n\tpublic void registerInstance(String applicationName, String ip, Integer port) {\n\t\ttry {\n\t\t\tthis.namingService().registerInstance(applicationName,\n\t\t\t\t\tsidecarNacosDiscoveryProperties.getGroup(), ip, port);\n\t\t}\n\t\tcatch (NacosException e) {\n\t\t\tlog.warn(\"nacos exception happens\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void deregisterInstance(String applicationName, String ip, Integer port) {\n\t\ttry {\n\t\t\tthis.namingService().deregisterInstance(applicationName,\n\t\t\t\t\tsidecarNacosDiscoveryProperties.getGroup(), ip, port);\n\t\t}\n\t\tcatch (NacosException e) {\n\t\t\tlog.warn(\"nacos exception happens\", e);\n\t\t}\n\t}\n\n\tprivate NamingService namingService() {\n\t\treturn nacosServiceManager\n\t\t\t\t.getNamingService();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/nacos/SidecarNacosDiscoveryProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.sidecar.nacos;\n\nimport com.alibaba.cloud.nacos.NacosDiscoveryProperties;\nimport com.alibaba.cloud.sidecar.SidecarProperties;\n\nimport org.springframework.util.StringUtils;\n\n/**\n * @author yuhuangbin\n */\npublic class SidecarNacosDiscoveryProperties extends NacosDiscoveryProperties {\n\n\tSidecarProperties sidecarProperties;\n\n\tpublic SidecarNacosDiscoveryProperties(SidecarProperties sidecarProperties) {\n\t\tthis.sidecarProperties = sidecarProperties;\n\t}\n\n\t@Override\n\tpublic void init() throws Exception {\n\t\tsuper.init();\n\n\t\tString ip = sidecarProperties.getIp();\n\t\tif (StringUtils.hasText(ip)) {\n\t\t\tthis.setIp(ip);\n\t\t}\n\n\t\tInteger port = sidecarProperties.getPort();\n\t\tthis.setPort(port);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports",
    "content": "com.alibaba.cloud.sidecar.nacos.SidecarNacosAutoConfiguration\ncom.alibaba.cloud.sidecar.SidecarAutoConfiguration\ncom.alibaba.cloud.sidecar.consul.SidecarConsulAutoConfiguration\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-bus-rocketmq/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-starters</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>spring-cloud-starter-bus-rocketmq</artifactId>\n    <name>Spring Cloud Alibaba Bus RocketMQ</name>\n\n    <dependencies>\n\n        <!-- Spring Cloud Stream RocketMQ -->\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n        </dependency>\n\n        <!-- Spring Cloud Bus -->\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-bus</artifactId>\n        </dependency>\n\n    </dependencies>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-bus-rocketmq/src/main/java/com/alibaba/cloud/bus/rocketmq/autoconfigurate/RocketMQBusAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.bus.rocketmq.autoconfigurate;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.convert.RocketMQMessageConverter;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.cloud.bus.BusEnvironmentPostProcessor;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.messaging.converter.CompositeMessageConverter;\n\n/**\n * BusAutoConfiguration of rocketmq.\n *\n * @author <a href=\"mailto:819294006@qq.com\">Sorie</a>\n * @see BusEnvironmentPostProcessor\n */\n@Configuration(proxyBeanMethods = false)\npublic class RocketMQBusAutoConfiguration {\n\t/**\n\t * issue: https://github.com/alibaba/spring-cloud-alibaba/issues/2742\n\t * if you want to customize a bean, please use this BeanName {@code RocketMQMessageConverter.DEFAULT_NAME}.\n\t */\n\t@Bean(RocketMQMessageConverter.DEFAULT_NAME)\n\t@ConditionalOnMissingBean(name = { RocketMQMessageConverter.DEFAULT_NAME })\n\tpublic CompositeMessageConverter rocketMQMessageConverter() {\n\t\treturn new RocketMQMessageConverter().getMessageConverter();\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-bus-rocketmq/src/main/java/com/alibaba/cloud/bus/rocketmq/env/RocketMQBusEnvironmentPostProcessor.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.bus.rocketmq.env;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport org.springframework.boot.EnvironmentPostProcessor;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.cloud.bus.BusEnvironmentPostProcessor;\nimport org.springframework.core.Ordered;\nimport org.springframework.core.env.ConfigurableEnvironment;\nimport org.springframework.core.env.MapPropertySource;\nimport org.springframework.core.env.MutablePropertySources;\nimport org.springframework.core.env.PropertySource;\n\nimport static org.springframework.cloud.bus.BusConstants.INPUT;\n\n/**\n * The lowest precedence {@link EnvironmentPostProcessor} configures default RocketMQ Bus\n * Properties that will be appended into {@link SpringApplication#defaultProperties}.\n *\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n * @since 0.2.1\n * @see BusEnvironmentPostProcessor\n */\npublic class RocketMQBusEnvironmentPostProcessor\n\t\timplements EnvironmentPostProcessor, Ordered {\n\n\t/**\n\t * The name of {@link PropertySource} of {@link SpringApplication#defaultProperties}.\n\t */\n\tprivate static final String PROPERTY_SOURCE_NAME = \"defaultProperties\";\n\n\t@Override\n\tpublic void postProcessEnvironment(ConfigurableEnvironment environment,\n\t\t\tSpringApplication application) {\n\n\t\taddDefaultPropertySource(environment);\n\n\t}\n\n\tprivate void addDefaultPropertySource(ConfigurableEnvironment environment) {\n\n\t\tMap<String, Object> map = new HashMap<String, Object>();\n\n\t\tconfigureDefaultProperties(map);\n\n\t\taddOrReplace(environment.getPropertySources(), map);\n\t}\n\n\tprivate void configureDefaultProperties(Map<String, Object> source) {\n\t\t// Required Properties\n\t\tString groupBindingPropertyName = createBindingPropertyName(INPUT, \"group\");\n\t\tString broadcastingPropertyName = createRocketMQPropertyName(INPUT,\n\t\t\t\t\"broadcasting\");\n\t\tsource.put(groupBindingPropertyName, \"rocketmq-bus-group\");\n\t\tsource.put(broadcastingPropertyName, \"true\");\n\t}\n\n\tprivate String createRocketMQPropertyName(String channel, String propertyName) {\n\t\treturn \"spring.cloud.stream.rocketmq.bindings.\" + INPUT + \".consumer.\"\n\t\t\t\t+ propertyName;\n\t}\n\n\tprivate String createBindingPropertyName(String channel, String propertyName) {\n\t\treturn \"spring.cloud.stream.bindings.\" + channel + \".\" + propertyName;\n\t}\n\n\t/**\n\t * Copy from.\n\t * {@link BusEnvironmentPostProcessor#addOrReplace(MutablePropertySources, Map)}\n\t * @param propertySources {@link MutablePropertySources}\n\t * @param map Default RocketMQ Bus Properties\n\t */\n\tprivate void addOrReplace(MutablePropertySources propertySources,\n\t\t\tMap<String, Object> map) {\n\t\tMapPropertySource target = null;\n\t\tif (propertySources.contains(PROPERTY_SOURCE_NAME)) {\n\t\t\tPropertySource<?> source = propertySources.get(PROPERTY_SOURCE_NAME);\n\t\t\tif (source instanceof MapPropertySource mapPropertySource) {\n\t\t\t\ttarget = mapPropertySource;\n\t\t\t\tfor (String key : map.keySet()) {\n\t\t\t\t\tif (!target.containsProperty(key)) {\n\t\t\t\t\t\ttarget.getSource().put(key, map.get(key));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (target == null) {\n\t\t\ttarget = new MapPropertySource(PROPERTY_SOURCE_NAME, map);\n\t\t}\n\t\tif (!propertySources.contains(PROPERTY_SOURCE_NAME)) {\n\t\t\tpropertySources.addLast(target);\n\t\t}\n\t}\n\n\t@Override\n\tpublic int getOrder() {\n\t\treturn LOWEST_PRECEDENCE;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-bus-rocketmq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports",
    "content": "com.alibaba.cloud.bus.rocketmq.autoconfigurate.RocketMQBusAutoConfiguration\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-bus-rocketmq/src/main/resources/META-INF/spring.factories",
    "content": "# EnvironmentPostProcessor\norg.springframework.boot.EnvironmentPostProcessor=\\\ncom.alibaba.cloud.bus.rocketmq.env.RocketMQBusEnvironmentPostProcessor\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-starters</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n    <name>Spring Cloud Starter Stream RocketMQ</name>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-health</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-stream</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-configuration-processor</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-actuator-autoconfigure</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.rocketmq</groupId>\n            <artifactId>rocketmq-client</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.apache.rocketmq</groupId>\n            <artifactId>rocketmq-acl</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>com.alibaba</groupId>\n                    <artifactId>fastjson</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>fastjson</artifactId>\n        </dependency>\n        <!-- Testing -->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQBeanContainerCache;\nimport com.alibaba.cloud.stream.binder.rocketmq.extend.ErrorAcknowledgeHandler;\nimport com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.RocketMQInboundChannelAdapter;\nimport com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull.DefaultErrorAcknowledgeHandler;\nimport com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull.RocketMQMessageSource;\nimport com.alibaba.cloud.stream.binder.rocketmq.integration.outbound.RocketMQProducerMessageHandler;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQExtendedBindingProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.provisioning.RocketMQTopicProvisioner;\nimport com.alibaba.cloud.stream.binder.rocketmq.utils.RocketMQUtils;\nimport org.apache.rocketmq.remoting.protocol.NamespaceUtil;\n\nimport org.springframework.cloud.stream.binder.AbstractMessageChannelBinder;\nimport org.springframework.cloud.stream.binder.BinderSpecificPropertiesProvider;\nimport org.springframework.cloud.stream.binder.ExtendedConsumerProperties;\nimport org.springframework.cloud.stream.binder.ExtendedProducerProperties;\nimport org.springframework.cloud.stream.binder.ExtendedPropertiesBinder;\nimport org.springframework.cloud.stream.binding.MessageConverterConfigurer;\nimport org.springframework.cloud.stream.provisioning.ConsumerDestination;\nimport org.springframework.cloud.stream.provisioning.ProducerDestination;\nimport org.springframework.integration.StaticMessageHeaderAccessor;\nimport org.springframework.integration.acks.AcknowledgmentCallback;\nimport org.springframework.integration.channel.AbstractMessageChannel;\nimport org.springframework.integration.core.MessageProducer;\nimport org.springframework.integration.support.DefaultErrorMessageStrategy;\nimport org.springframework.integration.support.ErrorMessageStrategy;\nimport org.springframework.messaging.MessageChannel;\nimport org.springframework.messaging.MessageHandler;\nimport org.springframework.messaging.MessagingException;\nimport org.springframework.util.StringUtils;\n\n\n/**\n * A {@link org.springframework.cloud.stream.binder.Binder} that uses RocketMQ as the\n * underlying middleware.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class RocketMQMessageChannelBinder extends\n\t\tAbstractMessageChannelBinder<ExtendedConsumerProperties<RocketMQConsumerProperties>, ExtendedProducerProperties<RocketMQProducerProperties>, RocketMQTopicProvisioner>\n\t\timplements\n\t\tExtendedPropertiesBinder<MessageChannel, RocketMQConsumerProperties, RocketMQProducerProperties> {\n\n\tprivate final RocketMQExtendedBindingProperties extendedBindingProperties;\n\n\tprivate final RocketMQBinderConfigurationProperties binderConfigurationProperties;\n\n\tpublic RocketMQMessageChannelBinder(\n\t\t\tRocketMQBinderConfigurationProperties binderConfigurationProperties,\n\t\t\tRocketMQExtendedBindingProperties extendedBindingProperties,\n\t\t\tRocketMQTopicProvisioner provisioningProvider) {\n\t\tsuper(new String[0], provisioningProvider);\n\t\tthis.extendedBindingProperties = extendedBindingProperties;\n\t\tthis.binderConfigurationProperties = binderConfigurationProperties;\n\t}\n\n\t@Override\n\tprotected MessageHandler createProducerMessageHandler(ProducerDestination destination,\n\t\t\tExtendedProducerProperties<RocketMQProducerProperties> extendedProducerProperties,\n\t\t\tMessageChannel channel, MessageChannel errorChannel) throws Exception {\n\t\tif (!extendedProducerProperties.getExtension().getEnabled()) {\n\t\t\tthrow new RuntimeException(\"Binding for channel \" + destination.getName()\n\t\t\t\t\t+ \" has been disabled, message can't be delivered\");\n\t\t}\n\t\tRocketMQProducerProperties mqProducerProperties = RocketMQUtils\n\t\t\t\t.mergeRocketMQProperties(binderConfigurationProperties,\n\t\t\t\t\t\textendedProducerProperties.getExtension());\n\t\tRocketMQProducerMessageHandler messageHandler = new RocketMQProducerMessageHandler(\n\t\t\t\tdestination, extendedProducerProperties, mqProducerProperties);\n\t\tmessageHandler.setApplicationContext(this.getApplicationContext());\n\t\tif (errorChannel != null) {\n\t\t\tmessageHandler.setSendFailureChannel(errorChannel);\n\t\t}\n\t\tMessageConverterConfigurer.PartitioningInterceptor partitioningInterceptor = ((AbstractMessageChannel) channel)\n\t\t\t\t.getInterceptors().stream()\n\t\t\t\t.filter(channelInterceptor -> channelInterceptor instanceof MessageConverterConfigurer.PartitioningInterceptor)\n\t\t\t\t.map(channelInterceptor -> ((MessageConverterConfigurer.PartitioningInterceptor) channelInterceptor))\n\t\t\t\t.findFirst().orElse(null);\n\t\tmessageHandler.setPartitioningInterceptor(partitioningInterceptor);\n\t\tmessageHandler.setBeanFactory(this.getApplicationContext().getBeanFactory());\n\t\tmessageHandler.setErrorMessageStrategy(this.getErrorMessageStrategy());\n\t\treturn messageHandler;\n\t}\n\n\t@Override\n\tprotected MessageHandler createProducerMessageHandler(ProducerDestination destination,\n\t\t\tExtendedProducerProperties<RocketMQProducerProperties> producerProperties,\n\t\t\tMessageChannel errorChannel) throws Exception {\n\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\"The abstract binder should not call this method\");\n\t}\n\n\t@Override\n\tprotected MessageProducer createConsumerEndpoint(ConsumerDestination destination,\n\t\t\tString group,\n\t\t\tExtendedConsumerProperties<RocketMQConsumerProperties> extendedConsumerProperties)\n\t\t\tthrows Exception {\n\t\tboolean anonymous = !StringUtils.hasLength(group);\n\t\t/***\n\t\t * \tWhen using DLQ, at least the group property must be provided for proper naming of the DLQ destination\n\t\t *  According to https://docs.spring.io/spring-cloud-stream/docs/3.2.1/reference/html/spring-cloud-stream.html#spring-cloud-stream-reference\n\t\t */\n\t\tif (anonymous && NamespaceUtil.isDLQTopic(destination.getName())) {\n\t\t\tthrow new RuntimeException(\n\t\t\t\t\t\"group must be configured for DLQ\" + destination.getName());\n\t\t}\n\t\tgroup = anonymous ? RocketMQUtils.anonymousGroup(destination.getName()) : group;\n\n\t\tRocketMQUtils.mergeRocketMQProperties(binderConfigurationProperties,\n\t\t\t\textendedConsumerProperties.getExtension());\n\t\textendedConsumerProperties.getExtension().setGroup(group);\n\n\t\tRocketMQInboundChannelAdapter inboundChannelAdapter = new RocketMQInboundChannelAdapter(\n\t\t\t\tdestination.getName(), extendedConsumerProperties);\n\t\tinboundChannelAdapter.setBeanFactory(this.getApplicationContext().getBeanFactory());\n\t\tErrorInfrastructure errorInfrastructure = registerErrorInfrastructure(destination,\n\t\t\t\tgroup, extendedConsumerProperties);\n\t\tif (extendedConsumerProperties.getMaxAttempts() > 1) {\n\t\t\tinboundChannelAdapter\n\t\t\t\t\t.setRetryTemplate(buildRetryTemplate(extendedConsumerProperties));\n\t\t\tinboundChannelAdapter.setRecoveryCallback(errorInfrastructure.getRecoverer());\n\t\t}\n\t\telse {\n\t\t\tinboundChannelAdapter.setErrorChannel(errorInfrastructure.getErrorChannel());\n\t\t}\n\t\treturn inboundChannelAdapter;\n\t}\n\n\t@Override\n\tprotected PolledConsumerResources createPolledConsumerResources(String name,\n\t\t\tString group, ConsumerDestination destination,\n\t\t\tExtendedConsumerProperties<RocketMQConsumerProperties> extendedConsumerProperties) {\n\t\tRocketMQUtils.mergeRocketMQProperties(binderConfigurationProperties,\n\t\t\t\textendedConsumerProperties.getExtension());\n\t\textendedConsumerProperties.getExtension().setGroup(group);\n\t\tRocketMQMessageSource messageSource = new RocketMQMessageSource(name,\n\t\t\t\textendedConsumerProperties);\n\t\treturn new PolledConsumerResources(messageSource, registerErrorInfrastructure(\n\t\t\t\tdestination, group, extendedConsumerProperties, true));\n\t}\n\n\t@Override\n\tprotected MessageHandler getPolledConsumerErrorMessageHandler(\n\t\t\tConsumerDestination destination, String group,\n\t\t\tExtendedConsumerProperties<RocketMQConsumerProperties> properties) {\n\t\treturn message -> {\n\t\t\tif (message.getPayload() instanceof MessagingException payload) {\n\t\t\t\tAcknowledgmentCallback ack = StaticMessageHeaderAccessor\n\t\t\t\t\t\t.getAcknowledgmentCallback(\n\t\t\t\t\t\t\t\tpayload.getFailedMessage());\n\t\t\t\tif (ack != null) {\n\t\t\t\t\tErrorAcknowledgeHandler handler = RocketMQBeanContainerCache.getBean(\n\t\t\t\t\t\t\tproperties.getExtension().getPull().getErrAcknowledge(),\n\t\t\t\t\t\t\tErrorAcknowledgeHandler.class,\n\t\t\t\t\t\t\tnew DefaultErrorAcknowledgeHandler());\n\t\t\t\t\tack.acknowledge(\n\t\t\t\t\t\t\thandler.handler(payload.getFailedMessage()));\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Binders can return an {@link ErrorMessageStrategy} for building error messages;\n\t * binder implementations typically might add extra headers to the error message.\n\t * @return the implementation - may be null.\n\t */\n\t@Override\n\tprotected ErrorMessageStrategy getErrorMessageStrategy() {\n\t\t// It can be extended to custom if necessary.\n\t\treturn new DefaultErrorMessageStrategy();\n\t}\n\n\t@Override\n\tpublic RocketMQConsumerProperties getExtendedConsumerProperties(String channelName) {\n\t\treturn this.extendedBindingProperties.getExtendedConsumerProperties(channelName);\n\t}\n\n\t@Override\n\tpublic RocketMQProducerProperties getExtendedProducerProperties(String channelName) {\n\t\treturn this.extendedBindingProperties.getExtendedProducerProperties(channelName);\n\t}\n\n\t@Override\n\tpublic String getDefaultsPrefix() {\n\t\treturn this.extendedBindingProperties.getDefaultsPrefix();\n\t}\n\n\t@Override\n\tpublic Class<? extends BinderSpecificPropertiesProvider> getExtendedPropertiesEntryClass() {\n\t\treturn this.extendedBindingProperties.getExtendedPropertiesEntryClass();\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/actuator/RocketMQBinderHealthIndicator.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.actuator;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation;\nimport com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager;\n\nimport org.springframework.boot.health.contributor.AbstractHealthIndicator;\nimport org.springframework.boot.health.contributor.Health;\n\n/**\n * @author Timur Valiev\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class RocketMQBinderHealthIndicator extends AbstractHealthIndicator {\n\n\t@Override\n\tprotected void doHealthCheck(Health.Builder builder) throws Exception {\n\t\tif (InstrumentationManager.getHealthInstrumentations().stream()\n\t\t\t\t.allMatch(Instrumentation::isUp)) {\n\t\t\tbuilder.up();\n\t\t\treturn;\n\t\t}\n\t\tif (InstrumentationManager.getHealthInstrumentations().stream()\n\t\t\t\t.allMatch(Instrumentation::isOutOfService)) {\n\t\t\tbuilder.outOfService();\n\t\t\treturn;\n\t\t}\n\t\tbuilder.down();\n\t\tInstrumentationManager.getHealthInstrumentations().stream()\n\t\t\t\t.filter(instrumentation -> !instrumentation.isStarted())\n\t\t\t\t.forEach(instrumentation1 -> builder\n\t\t\t\t\t\t.withException(instrumentation1.getStartException()));\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/aot/hint/RocketMQConsumerPropertiesHints.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.aot.hint;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Method;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;\n\nimport org.springframework.aot.hint.ExecutableMode;\nimport org.springframework.aot.hint.RuntimeHints;\nimport org.springframework.aot.hint.RuntimeHintsRegistrar;\nimport org.springframework.util.ReflectionUtils;\n\n/**\n * @author ChengPu raozihao\n */\npublic class RocketMQConsumerPropertiesHints implements RuntimeHintsRegistrar {\n\n\t@Override\n\tpublic void registerHints(RuntimeHints hints, ClassLoader classLoader) {\n\t\tConstructor<RocketMQConsumerProperties> constructor;\n\t\ttry {\n\t\t\tconstructor = RocketMQConsumerProperties.class.getConstructor();\n\t\t}\n\t\tcatch (NoSuchMethodException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\thints.reflection().registerConstructor(constructor, ExecutableMode.INVOKE);\n\t\t// setMessageModel\n\t\tMethod setMessageModel = ReflectionUtils.findMethod(RocketMQConsumerProperties.class, \"setMessageModel\", String.class);\n\t\thints.reflection().registerMethod(setMessageModel, ExecutableMode.INVOKE);\n\t\t// getPush\n\t\tMethod getPush = ReflectionUtils.findMethod(RocketMQConsumerProperties.class, \"getPush\");\n\t\thints.reflection().registerMethod(getPush, ExecutableMode.INVOKE);\n\t\t// setSubscription\n\t\tMethod setSubscription = ReflectionUtils.findMethod(RocketMQConsumerProperties.class, \"setSubscription\", String.class);\n\t\thints.reflection().registerMethod(setSubscription, ExecutableMode.INVOKE);\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/aot/hint/RocketMQSpecificPropertiesProviderHints.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.aot.hint;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Method;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQSpecificPropertiesProvider;\n\nimport org.springframework.aot.hint.ExecutableMode;\nimport org.springframework.aot.hint.RuntimeHints;\nimport org.springframework.aot.hint.RuntimeHintsRegistrar;\nimport org.springframework.util.ReflectionUtils;\n\n/**\n * @author ChengPu raozihao\n */\npublic class RocketMQSpecificPropertiesProviderHints implements RuntimeHintsRegistrar {\n\n\t@Override\n\tpublic void registerHints(RuntimeHints hints, ClassLoader classLoader) {\n\t\tConstructor<RocketMQSpecificPropertiesProvider> constructor;\n\t\ttry {\n\t\t\tconstructor = RocketMQSpecificPropertiesProvider.class.getConstructor();\n\t\t}\n\t\tcatch (NoSuchMethodException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\thints.reflection().registerConstructor(constructor, ExecutableMode.INVOKE);\n\t\t// getConsumer\n\t\tMethod getConsumer = ReflectionUtils.findMethod(RocketMQSpecificPropertiesProvider.class, \"getConsumer\");\n\t\thints.reflection().registerMethod(getConsumer, ExecutableMode.INVOKE);\n\t\t// setConsumer\n\t\tMethod setConsumer = ReflectionUtils.findMethod(RocketMQSpecificPropertiesProvider.class, \"setConsumer\", RocketMQConsumerProperties.class);\n\t\thints.reflection().registerMethod(setConsumer, ExecutableMode.INVOKE);\n\t\t// getProducer\n\t\tMethod getProducer = ReflectionUtils.findMethod(RocketMQSpecificPropertiesProvider.class, \"getProducer\");\n\t\thints.reflection().registerMethod(getProducer, ExecutableMode.INVOKE);\n\t\t// setProducer\n\t\tMethod setProducer = ReflectionUtils.findMethod(RocketMQSpecificPropertiesProvider.class, \"setProducer\", RocketMQProducerProperties.class);\n\t\thints.reflection().registerMethod(setProducer, ExecutableMode.INVOKE);\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.convert.RocketMQMessageConverter;\nimport com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQConfigBeanPostProcessor;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.context.properties.source.ConfigurationPropertyName;\nimport org.springframework.cloud.stream.config.BindingHandlerAdvise.MappingsProvider;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.messaging.converter.CompositeMessageConverter;\nimport org.springframework.messaging.converter.MessageConverter;\n\n@Configuration\npublic class ExtendedBindingHandlerMappingsProviderConfiguration {\n\n\t@Bean\n\tpublic MappingsProvider rocketExtendedPropertiesDefaultMappingsProvider() {\n\t\treturn () -> {\n\t\t\tMap<ConfigurationPropertyName, ConfigurationPropertyName> mappings = new HashMap<>();\n\t\t\tmappings.put(\n\t\t\t\t\tConfigurationPropertyName.of(\"spring.cloud.stream.rocketmq.bindings\"),\n\t\t\t\t\tConfigurationPropertyName.of(\"spring.cloud.stream.rocketmq.default\"));\n\t\t\tmappings.put(\n\t\t\t\t\tConfigurationPropertyName.of(\"spring.cloud.stream.rocketmq.streams\"),\n\t\t\t\t\tConfigurationPropertyName\n\t\t\t\t\t\t\t.of(\"spring.cloud.stream.rocketmq.streams.default\"));\n\t\t\treturn mappings;\n\t\t};\n\t}\n\n\t@Bean\n\tpublic static RocketMQConfigBeanPostProcessor rocketMQConfigBeanPostProcessor() {\n\t\treturn new RocketMQConfigBeanPostProcessor();\n\t}\n\n\n\t/**\n\t * if you want to customize a bean, please use this BeanName {@code RocketMQMessageConverter.DEFAULT_NAME}.\n\t */\n\t@Bean(RocketMQMessageConverter.DEFAULT_NAME)\n\t@ConditionalOnMissingBean(name = { RocketMQMessageConverter.DEFAULT_NAME })\n\tpublic CompositeMessageConverter rocketMQMessageConverter() {\n\t\treturn new RocketMQMessageConverter().getMessageConverter();\n\t}\n\n\t/**\n\t * Register message converter to adapte Spring Cloud Stream.\n\t * Refer to https://docs.spring.io/spring-cloud-stream/docs/current/reference/html/spring-cloud-stream.html#spring-cloud-stream-overview-user-defined-message-converters .\n\t * @return message converter.\n\t */\n\t@Bean\n\tpublic MessageConverter rocketMQCustomMessageConverter() {\n\t\treturn new RocketMQMessageConverter();\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.RocketMQMessageChannelBinder;\nimport com.alibaba.cloud.stream.binder.rocketmq.actuator.RocketMQBinderHealthIndicator;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQExtendedBindingProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.provisioning.RocketMQTopicProvisioner;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator;\nimport org.springframework.boot.health.contributor.HealthIndicator;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * issue:https://github.com/alibaba/spring-cloud-alibaba/issues/1681 .\n *\n * @author Timur Valiev\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n * @author freeman\n */\n@Configuration(proxyBeanMethods = false)\n@EnableConfigurationProperties({ RocketMQExtendedBindingProperties.class,\n\t\tRocketMQBinderConfigurationProperties.class })\npublic class RocketMQBinderAutoConfiguration {\n\n\t@Autowired\n\tprivate RocketMQExtendedBindingProperties extendedBindingProperties;\n\n\t@Autowired\n\tprivate RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties;\n\n\t@Bean\n\tpublic RocketMQTopicProvisioner rocketMQTopicProvisioner() {\n\t\treturn new RocketMQTopicProvisioner();\n\t}\n\n\t@Bean\n\tpublic RocketMQMessageChannelBinder rocketMQMessageChannelBinder(\n\t\t\tRocketMQTopicProvisioner provisioningProvider) {\n\t\treturn new RocketMQMessageChannelBinder(rocketBinderConfigurationProperties,\n\t\t\t\textendedBindingProperties, provisioningProvider);\n\t}\n\n\t@Configuration(proxyBeanMethods = false)\n\t@ConditionalOnClass(HealthIndicator.class)\n\t@ConditionalOnEnabledHealthIndicator(\"rocketmq\")\n\tstatic class RocketMQBinderHealthIndicatorConfiguration {\n\n\t\t@Bean\n\t\tpublic RocketMQBinderHealthIndicator rocketMQBinderHealthIndicator() {\n\t\t\treturn new RocketMQBinderHealthIndicator();\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/constant/RocketMQConst.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.constant;\n\nimport org.apache.rocketmq.common.message.MessageConst;\n\n/**\n * @author zkzlx\n */\npublic class RocketMQConst extends MessageConst {\n\n\t/**\n\t * Default NameServer value.\n\t */\n\tpublic static final String DEFAULT_NAME_SERVER = \"127.0.0.1:9876\";\n\n\t/**\n\t * Default group for SCS RocketMQ Binder.\n\t */\n\tpublic static final String DEFAULT_GROUP = \"anonymous\";\n\n\t/**\n\t * user args for SCS RocketMQ Binder.\n\t */\n\tpublic static final String USER_TRANSACTIONAL_ARGS = \"TRANSACTIONAL_ARGS\";\n\n\t/**\n\t * It is mainly provided for conversion between rocketMq-message and Spring-message,\n\t * and parameters are passed through HEADERS.\n\t */\n\tpublic static class Headers {\n\n\t\t/**\n\t\t * keys for SCS RocketMQ Headers.\n\t\t */\n\t\tpublic static final String KEYS = MessageConst.PROPERTY_KEYS;\n\n\t\t/**\n\t\t * tags for SCS RocketMQ Headers.\n\t\t */\n\t\tpublic static final String TAGS = MessageConst.PROPERTY_TAGS;\n\n\t\t/**\n\t\t * topic for SCS RocketMQ Headers.\n\t\t */\n\t\tpublic static final String TOPIC = \"MQ_TOPIC\";\n\n\t\t/**\n\t\t * The ID of the message.\n\t\t */\n\t\tpublic static final String MESSAGE_ID = \"MQ_MESSAGE_ID\";\n\n\t\t/**\n\t\t * The timestamp that the message producer invokes the message sending API.\n\t\t */\n\t\tpublic static final String BORN_TIMESTAMP = \"MQ_BORN_TIMESTAMP\";\n\n\t\t/**\n\t\t * The IP and port number of the message producer.\n\t\t */\n\t\tpublic static final String BORN_HOST = \"MQ_BORN_HOST\";\n\n\t\t/**\n\t\t * Message flag, MQ is not processed and is available for use by applications.\n\t\t */\n\t\tpublic static final String FLAG = \"MQ_FLAG\";\n\n\t\t/**\n\t\t * Message consumption queue ID.\n\t\t */\n\t\tpublic static final String QUEUE_ID = \"MQ_QUEUE_ID\";\n\n\t\t/**\n\t\t * Message system Flag, such as whether or not to compress, whether or not to\n\t\t * transactional messages.\n\t\t */\n\t\tpublic static final String SYS_FLAG = \"MQ_SYS_FLAG\";\n\n\t\t/**\n\t\t * The transaction ID of the transaction message.\n\t\t */\n\t\tpublic static final String TRANSACTION_ID = \"MQ_TRANSACTION_ID\";\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.convert;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.springframework.messaging.Message;\nimport org.springframework.messaging.converter.AbstractMessageConverter;\nimport org.springframework.messaging.converter.ByteArrayMessageConverter;\nimport org.springframework.messaging.converter.CompositeMessageConverter;\nimport org.springframework.messaging.converter.JacksonJsonMessageConverter;\nimport org.springframework.messaging.converter.MessageConverter;\nimport org.springframework.messaging.converter.StringMessageConverter;\nimport org.springframework.util.ClassUtils;\n\n/**\n * The default message converter of rocketMq,its bean name is {@link #DEFAULT_NAME} .\n *\n * @author zkzlx\n */\npublic class RocketMQMessageConverter extends AbstractMessageConverter {\n\n\t/**\n\t * if you want to customize a bean, please use the BeanName.\n\t */\n\tpublic static final String DEFAULT_NAME = \"com.alibaba.cloud.stream.binder.rocketmq.convert.RocketMQMessageConverter\";\n\n\tprivate static final boolean JACKSON_PRESENT;\n\n\tprivate static final boolean FASTJSON_PRESENT;\n\n\tstatic {\n\t\tClassLoader classLoader = RocketMQMessageConverter.class.getClassLoader();\n\t\tJACKSON_PRESENT = ClassUtils\n\t\t\t\t.isPresent(\"tools.jackson.core.JsonToken\", classLoader)\n\t\t\t\t&& ClassUtils.isPresent(\"tools.jackson.core.JsonGenerator\",\n\t\t\t\t\t\tclassLoader);\n\t\tFASTJSON_PRESENT = ClassUtils.isPresent(\"com.alibaba.fastjson.JSON\", classLoader)\n\t\t\t\t&& ClassUtils.isPresent(\n\t\t\t\t\t\t\"com.alibaba.fastjson.support.config.FastJsonConfig\",\n\t\t\t\t\t\tclassLoader);\n\t}\n\n\tprivate CompositeMessageConverter messageConverter;\n\n\tpublic RocketMQMessageConverter() {\n\t\tList<MessageConverter> messageConverters = new ArrayList<>();\n\t\tByteArrayMessageConverter byteArrayMessageConverter = new ByteArrayMessageConverter();\n\t\tbyteArrayMessageConverter.setContentTypeResolver(null);\n\t\tmessageConverters.add(byteArrayMessageConverter);\n\t\tmessageConverters.add(new StringMessageConverter());\n\t\tif (JACKSON_PRESENT) {\n\t\t\tmessageConverters.add(new JacksonJsonMessageConverter());\n\t\t}\n\t\tif (FASTJSON_PRESENT) {\n\t\t\ttry {\n\t\t\t\tmessageConverters.add((MessageConverter) ClassUtils.forName(\n\t\t\t\t\t\t\"com.alibaba.fastjson.support.spring.messaging.MappingFastJsonMessageConverter\",\n\t\t\t\t\t\tClassUtils.getDefaultClassLoader()).newInstance());\n\t\t\t}\n\t\t\tcatch (ClassNotFoundException | IllegalAccessException\n\t\t\t\t\t| InstantiationException ignored) {\n\t\t\t\t// ignore this exception\n\t\t\t}\n\t\t}\n\t\tmessageConverter = new CompositeMessageConverter(messageConverters);\n\t}\n\n\tpublic CompositeMessageConverter getMessageConverter() {\n\t\treturn messageConverter;\n\t}\n\n\tpublic void setMessageConverter(CompositeMessageConverter messageConverter) {\n\t\tthis.messageConverter = messageConverter;\n\t}\n\n\t/**\n\t * support all classes.\n\t * @param clazz classes.\n\t * @return awayls true.\n\t */\n\t@Override\n\tprotected boolean supports(Class<?> clazz) {\n\t\treturn true;\n\t}\n\n\t/**\n\t * Convert the message payload from serialized form to an Object by RocketMQMessageConverter.\n\t * @param message the input message\n\t * @param targetClass the target class for the conversion\n\t * @param conversionHint an extra object passed to the {@link MessageConverter},\n\t * e.g. the associated {@code MethodParameter} (may be {@code null}}\n\t * @return the result of the conversion, or {@code null} if the converter cannot\n\t * perform the conversion\n\t * @since 4.2\n\t */\n\t@Override\n\tprotected Object convertFromInternal(Message<?> message, Class<?> targetClass, Object conversionHint) {\n\t\tObject payload = null;\n\t\tfor (MessageConverter converter : getMessageConverter().getConverters()) {\n\t\t\ttry {\n\t\t\t\tpayload = converter.fromMessage(message, targetClass);\n\t\t\t}\n\t\t\tcatch (Exception ignore) {\n\t\t\t}\n\t\t\tif (payload != null) {\n\t\t\t\treturn payload;\n\t\t\t}\n\t\t}\n\t\tif (payload == null && logger.isDebugEnabled()) {\n\t\t\tlogger.debug(\"Can convert message \" + message.toString());\n\t\t}\n\t\treturn payload;\n\t}\n\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.custom;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.extend.ErrorAcknowledgeHandler;\nimport org.apache.rocketmq.client.consumer.AllocateMessageQueueStrategy;\nimport org.apache.rocketmq.client.consumer.listener.MessageListener;\nimport org.apache.rocketmq.client.hook.CheckForbiddenHook;\nimport org.apache.rocketmq.client.hook.SendMessageHook;\nimport org.apache.rocketmq.client.producer.MessageQueueSelector;\nimport org.apache.rocketmq.client.producer.SendCallback;\nimport org.apache.rocketmq.client.producer.TransactionListener;\n\nimport org.springframework.messaging.converter.CompositeMessageConverter;\nimport org.springframework.util.StringUtils;\n\n/**\n * Gets the beans configured in the configuration file.\n *\n * @author junboXiang\n */\npublic final class RocketMQBeanContainerCache {\n\n\tprivate RocketMQBeanContainerCache() {\n\t}\n\n\tprivate static final Class<?>[] CLASSES = new Class[] {\n\t\t\tCompositeMessageConverter.class, AllocateMessageQueueStrategy.class,\n\t\t\tMessageQueueSelector.class, MessageListener.class, TransactionListener.class,\n\t\t\tSendCallback.class, CheckForbiddenHook.class, SendMessageHook.class,\n\t\t\tErrorAcknowledgeHandler.class };\n\n\tprivate static final Map<String, Object> BEANS_CACHE = new ConcurrentHashMap<>();\n\n\tstatic void putBean(String beanName, Object beanObj) {\n\t\tBEANS_CACHE.put(beanName, beanObj);\n\t}\n\n\tstatic Class<?>[] getClassAry() {\n\t\treturn CLASSES;\n\t}\n\n\tpublic static <T> T getBean(String beanName, Class<T> clazz) {\n\t\treturn getBean(beanName, clazz, null);\n\t}\n\n\tpublic static <T> T getBean(String beanName, Class<T> clazz, T defaultObj) {\n\t\tif (!StringUtils.hasLength(beanName)) {\n\t\t\treturn defaultObj;\n\t\t}\n\t\tObject obj = BEANS_CACHE.get(beanName);\n\t\tif (null == obj) {\n\t\t\treturn defaultObj;\n\t\t}\n\t\tif (clazz.isAssignableFrom(obj.getClass())) {\n\t\t\treturn (T) obj;\n\t\t}\n\t\treturn defaultObj;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQConfigBeanPostProcessor.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.custom;\n\nimport java.util.stream.Stream;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.config.BeanPostProcessor;\n\n/**\n * find RocketMQ bean by annotations.\n *\n * @author junboXiang\n *\n */\npublic class RocketMQConfigBeanPostProcessor implements BeanPostProcessor {\n\n\t@Override\n\tpublic Object postProcessAfterInitialization(Object bean, String beanName)\n\t\t\tthrows BeansException {\n\t\tStream.of(RocketMQBeanContainerCache.getClassAry()).forEach(clazz -> {\n\t\t\tif (clazz.isAssignableFrom(bean.getClass())) {\n\t\t\t\tRocketMQBeanContainerCache.putBean(beanName, bean);\n\t\t\t}\n\t\t});\n\t\treturn bean;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/extend/ErrorAcknowledgeHandler.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.extend;\n\nimport org.springframework.integration.acks.AcknowledgmentCallback.Status;\nimport org.springframework.messaging.Message;\n\n/**\n * @author zkzlx\n */\npublic interface ErrorAcknowledgeHandler {\n\n\t/**\n\t * Ack state handling, including receive, reject, and retry, when a consumption\n\t * exception occurs.\n\t * @param message message\n\t * @return see {@link Status}\n\t */\n\tStatus handler(Message<?> message);\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.integration.inbound;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQBeanContainerCache;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.utils.RocketMQUtils;\nimport org.apache.rocketmq.acl.common.AclClientRPCHook;\nimport org.apache.rocketmq.acl.common.SessionCredentials;\nimport org.apache.rocketmq.client.AccessChannel;\nimport org.apache.rocketmq.client.consumer.AllocateMessageQueueStrategy;\nimport org.apache.rocketmq.client.consumer.DefaultLitePullConsumer;\nimport org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;\nimport org.apache.rocketmq.client.consumer.rebalance.AllocateMessageQueueAveragely;\nimport org.apache.rocketmq.remoting.RPCHook;\nimport org.apache.rocketmq.remoting.protocol.NamespaceUtil;\nimport org.apache.rocketmq.remoting.protocol.heartbeat.MessageModel;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.cloud.stream.binder.ExtendedConsumerProperties;\nimport org.springframework.util.Assert;\nimport org.springframework.util.StringUtils;\n\n/**\n * Extended function related to producer . eg:initial\n *\n * @author zkzlx\n */\npublic final class RocketMQConsumerFactory {\n\n\tprivate RocketMQConsumerFactory() {\n\t}\n\n\tprivate final static Logger log = LoggerFactory\n\t\t\t.getLogger(RocketMQConsumerFactory.class);\n\n\tpublic static DefaultMQPushConsumer initPushConsumer(\n\t\t\tExtendedConsumerProperties<RocketMQConsumerProperties> extendedConsumerProperties) {\n\t\tRocketMQConsumerProperties consumerProperties = extendedConsumerProperties\n\t\t\t\t.getExtension();\n\t\tAssert.notNull(consumerProperties.getGroup(),\n\t\t\t\t\"Property 'group' is required - consumerGroup\");\n\t\tAssert.notNull(consumerProperties.getNameServer(),\n\t\t\t\t\"Property 'nameServer' is required\");\n\t\tAllocateMessageQueueStrategy allocateMessageQueueStrategy = RocketMQBeanContainerCache\n\t\t\t\t.getBean(consumerProperties.getAllocateMessageQueueStrategy(),\n\t\t\t\t\t\tAllocateMessageQueueStrategy.class,\n\t\t\t\t\t\tnew AllocateMessageQueueAveragely());\n\t\tRPCHook rpcHook = null;\n\t\tif (StringUtils.hasLength(consumerProperties.getAccessKey())\n\t\t\t\t&& StringUtils.hasLength(consumerProperties.getSecretKey())) {\n\t\t\trpcHook = new AclClientRPCHook(\n\t\t\t\t\tnew SessionCredentials(consumerProperties.getAccessKey(),\n\t\t\t\t\t\t\tconsumerProperties.getSecretKey()));\n\t\t}\n\t\tDefaultMQPushConsumer consumer = new DefaultMQPushConsumer(\n\t\t\t\tconsumerProperties.getGroup(), rpcHook, allocateMessageQueueStrategy,\n\t\t\t\tconsumerProperties.getEnableMsgTrace(),\n\t\t\t\tconsumerProperties.getCustomizedTraceTopic());\n\t\tconsumer.setVipChannelEnabled(\n\t\t\t\tnull == rpcHook && consumerProperties.getVipChannelEnabled());\n\t\tconsumer.setInstanceName(\n\t\t\t\tRocketMQUtils.getInstanceName(rpcHook, consumerProperties.getGroup()));\n\t\tconsumer.setNamespace(consumerProperties.getNamespace());\n\t\tconsumer.setNamespaceV2(consumerProperties.getNamespaceV2());\n\t\tconsumer.setNamesrvAddr(consumerProperties.getNameServer());\n\t\tconsumer.setMessageModel(getMessageModel(consumerProperties.getMessageModel()));\n\t\tconsumer.setUseTLS(consumerProperties.getUseTLS());\n\t\tconsumer.setPullTimeDelayMillsWhenException(\n\t\t\t\tconsumerProperties.getPullTimeDelayMillsWhenException());\n\t\tconsumer.setPullBatchSize(consumerProperties.getPullBatchSize());\n\t\tconsumer.setConsumeFromWhere(consumerProperties.getConsumeFromWhere());\n\t\tconsumer.setHeartbeatBrokerInterval(\n\t\t\t\tconsumerProperties.getHeartbeatBrokerInterval());\n\t\tconsumer.setPersistConsumerOffsetInterval(\n\t\t\t\tconsumerProperties.getPersistConsumerOffsetInterval());\n\t\tconsumer.setPullInterval(consumerProperties.getPush().getPullInterval());\n\t\tconsumer.setConsumeThreadMin(extendedConsumerProperties.getConcurrency());\n\t\tconsumer.setConsumeThreadMax(extendedConsumerProperties.getConcurrency());\n\t\tconsumer.setUnitName(consumerProperties.getUnitName());\n\t\tconsumer.setMaxReconsumeTimes(\n\t\t\t\tconsumerProperties.getPush().getMaxReconsumeTimes());\n\t\tconsumer.setConsumeTimeout(consumerProperties.getPush().getConsumeTimeout());\n\t\tconsumer.setAccessChannel(AccessChannel.valueOf(consumerProperties.getAccessChannel()));\n\t\treturn consumer;\n\t}\n\n\t/**\n\t * todo Compatible with versions less than 4.6 ?\n\t * @param topic consumer topic.\n\t * @param extendedConsumerProperties extendedConsumerProperties\n\t * @return DefaultLitePullConsumer\n\t */\n\tpublic static DefaultLitePullConsumer initPullConsumer(\n\t\t\tString topic,\n\t\t\tExtendedConsumerProperties<RocketMQConsumerProperties> extendedConsumerProperties) {\n\t\tRocketMQConsumerProperties consumerProperties = extendedConsumerProperties\n\t\t\t\t.getExtension();\n\t\tboolean anonymous = !StringUtils.hasLength(consumerProperties.getGroup());\n\t\t/***\n\t\t * \tWhen using DLQ, at least the group property must be provided for proper naming of the DLQ destination\n\t\t *  According to https://docs.spring.io/spring-cloud-stream/docs/3.2.1/reference/html/spring-cloud-stream.html#spring-cloud-stream-reference\n\t\t */\n\t\tif (anonymous && NamespaceUtil.isDLQTopic(topic)) {\n\t\t\tthrow new RuntimeException(\n\t\t\t\t\t\"group must be configured for DLQ\" + topic);\n\t\t}\n\t\tif (anonymous) {\n\t\t\tconsumerProperties.setGroup(RocketMQUtils.anonymousGroup(topic));\n\t\t}\n\n\t\tAssert.notNull(consumerProperties.getNameServer(),\n\t\t\t\t\"Property 'nameServer' is required\");\n\t\tAllocateMessageQueueStrategy allocateMessageQueueStrategy = RocketMQBeanContainerCache\n\t\t\t\t.getBean(consumerProperties.getAllocateMessageQueueStrategy(),\n\t\t\t\t\t\tAllocateMessageQueueStrategy.class);\n\n\t\tRPCHook rpcHook = null;\n\t\tif (StringUtils.hasLength(consumerProperties.getAccessKey())\n\t\t\t\t&& StringUtils.hasLength(consumerProperties.getSecretKey())) {\n\t\t\trpcHook = new AclClientRPCHook(\n\t\t\t\t\tnew SessionCredentials(consumerProperties.getAccessKey(),\n\t\t\t\t\t\t\tconsumerProperties.getSecretKey()));\n\t\t}\n\n\t\tDefaultLitePullConsumer consumer = new DefaultLitePullConsumer(\n\t\t\t\tconsumerProperties.getNamespace(), consumerProperties.getGroup(),\n\t\t\t\trpcHook);\n\t\tconsumer.setVipChannelEnabled(\n\t\t\t\tnull == rpcHook && consumerProperties.getVipChannelEnabled());\n\t\tconsumer.setInstanceName(\n\t\t\t\tRocketMQUtils.getInstanceName(rpcHook, consumerProperties.getGroup()));\n\t\tif (null != allocateMessageQueueStrategy) {\n\t\t\tconsumer.setAllocateMessageQueueStrategy(allocateMessageQueueStrategy);\n\t\t}\n\t\tconsumer.setNamesrvAddr(consumerProperties.getNameServer());\n\t\tconsumer.setMessageModel(getMessageModel(consumerProperties.getMessageModel()));\n\t\tconsumer.setNamespaceV2(consumerProperties.getNamespaceV2());\n\t\tconsumer.setUseTLS(consumerProperties.getUseTLS());\n\t\tconsumer.setPullTimeDelayMillsWhenException(\n\t\t\t\tconsumerProperties.getPullTimeDelayMillsWhenException());\n\t\tconsumer.setConsumerTimeoutMillisWhenSuspend(\n\t\t\t\tconsumerProperties.getPull().getConsumerTimeoutMillisWhenSuspend());\n\t\tconsumer.setPullBatchSize(consumerProperties.getPullBatchSize());\n\t\tconsumer.setConsumeFromWhere(consumerProperties.getConsumeFromWhere());\n\t\tconsumer.setHeartbeatBrokerInterval(\n\t\t\t\tconsumerProperties.getHeartbeatBrokerInterval());\n\t\tconsumer.setPersistConsumerOffsetInterval(\n\t\t\t\tconsumerProperties.getPersistConsumerOffsetInterval());\n\t\tconsumer.setPollTimeoutMillis(\n\t\t\t\tconsumerProperties.getPull().getPollTimeoutMillis());\n\t\tconsumer.setPullThreadNums(extendedConsumerProperties.getConcurrency());\n\t\t// The internal queues are cached by a maximum of 1000\n\t\tconsumer.setPullThresholdForAll(extendedConsumerProperties.getExtension()\n\t\t\t\t.getPull().getPullThresholdForAll());\n\t\tconsumer.setUnitName(consumerProperties.getUnitName());\n\t\tconsumer.setAccessChannel(AccessChannel.valueOf(consumerProperties.getAccessChannel()));\n\t\treturn consumer;\n\t}\n\n\tprivate static MessageModel getMessageModel(String messageModel) {\n\t\tfor (MessageModel model : MessageModel.values()) {\n\t\t\tif (model.getModeCN().equalsIgnoreCase(messageModel)) {\n\t\t\t\treturn model;\n\t\t\t}\n\t\t}\n\t\treturn MessageModel.CLUSTERING;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.integration.inbound;\n\nimport java.util.List;\nimport java.util.function.Supplier;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation;\nimport com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQMessageConverterSupport;\nimport com.alibaba.cloud.stream.binder.rocketmq.utils.RocketMQUtils;\nimport org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;\nimport org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;\nimport org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus;\nimport org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;\nimport org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly;\nimport org.apache.rocketmq.common.message.MessageExt;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.cloud.stream.binder.ExtendedConsumerProperties;\nimport org.springframework.core.retry.RetryException;\nimport org.springframework.core.retry.RetryListener;\nimport org.springframework.core.retry.RetryPolicy;\nimport org.springframework.core.retry.RetryTemplate;\nimport org.springframework.core.retry.Retryable;\nimport org.springframework.integration.context.OrderlyShutdownCapable;\nimport org.springframework.integration.core.RecoveryCallback;\nimport org.springframework.integration.endpoint.MessageProducerSupport;\nimport org.springframework.integration.support.MessageBuilder;\nimport org.springframework.messaging.Message;\nimport org.springframework.messaging.MessagingException;\nimport org.springframework.util.Assert;\nimport org.springframework.util.CollectionUtils;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class RocketMQInboundChannelAdapter extends MessageProducerSupport\n\t\timplements OrderlyShutdownCapable {\n\n\tprivate static final Logger log = LoggerFactory\n\t\t\t.getLogger(RocketMQInboundChannelAdapter.class);\n\n\tprivate RetryTemplate retryTemplate;\n\n\tprivate RecoveryCallback<Object> recoveryCallback;\n\n\tprivate DefaultMQPushConsumer pushConsumer;\n\n\tprivate final String topic;\n\n\tprivate final ExtendedConsumerProperties<RocketMQConsumerProperties> extendedConsumerProperties;\n\n\tpublic RocketMQInboundChannelAdapter(String topic,\n\t\t\tExtendedConsumerProperties<RocketMQConsumerProperties> extendedConsumerProperties) {\n\t\tthis.topic = topic;\n\t\tthis.extendedConsumerProperties = extendedConsumerProperties;\n\t}\n\n\t@Override\n\tprotected void onInit() {\n\t\tif (extendedConsumerProperties.getExtension() == null\n\t\t\t\t|| !extendedConsumerProperties.getExtension().getEnabled()) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tsuper.onInit();\n\t\t\tif (this.retryTemplate != null) {\n\t\t\t\tAssert.state(getErrorChannel() == null,\n\t\t\t\t\t\t\"Cannot have an 'errorChannel' property when a 'RetryTemplate' is \"\n\t\t\t\t\t\t\t\t+ \"provided; use an 'ErrorMessageSendingRecoverer' in the 'recoveryCallback' property to \"\n\t\t\t\t\t\t\t\t+ \"send an error message when retries are exhausted\");\n\t\t\t\tthis.retryTemplate.setRetryListener(new RetryListener() {\n\t\t\t\t});\n\t\t\t}\n\t\t\tpushConsumer = RocketMQConsumerFactory\n\t\t\t\t\t.initPushConsumer(extendedConsumerProperties);\n\t\t\t// prepare register consumer message listener,the next step is to be\n\t\t\t// compatible with a custom MessageListener.\n\t\t\tif (extendedConsumerProperties.getExtension().getPush().getOrderly()) {\n\t\t\t\tpushConsumer.registerMessageListener((MessageListenerOrderly) (msgs,\n\t\t\t\t\t\tcontext) -> RocketMQInboundChannelAdapter.this\n\t\t\t\t\t\t\t\t.consumeMessage(msgs, () -> {\n\t\t\t\t\t\t\t\t\tcontext.setSuspendCurrentQueueTimeMillis(\n\t\t\t\t\t\t\t\t\t\t\textendedConsumerProperties.getExtension()\n\t\t\t\t\t\t\t\t\t\t\t\t\t.getPush()\n\t\t\t\t\t\t\t\t\t\t\t\t\t.getSuspendCurrentQueueTimeMillis());\n\t\t\t\t\t\t\t\t\treturn ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT;\n\t\t\t\t\t\t\t\t}, () -> ConsumeOrderlyStatus.SUCCESS));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpushConsumer.registerMessageListener((MessageListenerConcurrently) (msgs,\n\t\t\t\t\t\tcontext) -> RocketMQInboundChannelAdapter.this\n\t\t\t\t\t\t\t\t.consumeMessage(msgs, () -> {\n\t\t\t\t\t\t\t\t\tcontext.setDelayLevelWhenNextConsume(\n\t\t\t\t\t\t\t\t\t\t\textendedConsumerProperties.getExtension()\n\t\t\t\t\t\t\t\t\t\t\t\t\t.getPush()\n\t\t\t\t\t\t\t\t\t\t\t\t\t.getDelayLevelWhenNextConsume());\n\t\t\t\t\t\t\t\t\treturn ConsumeConcurrentlyStatus.RECONSUME_LATER;\n\t\t\t\t\t\t\t\t}, () -> ConsumeConcurrentlyStatus.CONSUME_SUCCESS));\n\t\t\t}\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tlog.error(\"DefaultMQPushConsumer init failed, Caused by \" + e.getMessage());\n\t\t\tthrow new MessagingException(MessageBuilder.withPayload(\n\t\t\t\t\t\"DefaultMQPushConsumer init failed, Caused by \" + e.getMessage())\n\t\t\t\t\t.build(), e);\n\t\t}\n\t}\n\n\t/**\n\t * The actual execution of a user-defined input consumption service method.\n\t * @param messageExtList rocket mq message list\n\t * @param failSupplier {@link ConsumeConcurrentlyStatus} or\n\t *     {@link ConsumeOrderlyStatus}\n\t * @param sucSupplier {@link ConsumeConcurrentlyStatus} or\n\t *     {@link ConsumeOrderlyStatus}\n\t * @param <R> object\n\t * @return R\n\t */\n\tprivate <R> R consumeMessage(List<MessageExt> messageExtList,\n\t\t\tSupplier<R> failSupplier, Supplier<R> sucSupplier) {\n\t\tif (CollectionUtils.isEmpty(messageExtList)) {\n\t\t\tthrow new MessagingException(\n\t\t\t\t\t\"DefaultMQPushConsumer consuming failed, Caused by messageExtList is empty\");\n\t\t}\n\t\tfor (MessageExt messageExt : messageExtList) {\n\t\t\ttry {\n\t\t\t\tMessage<?> message = RocketMQMessageConverterSupport\n\t\t\t\t\t\t.convertMessage2Spring(messageExt);\n\t\t\t\tif (this.retryTemplate != null) {\n\t\t\t\t\tthis.retryTemplate.setRetryListener(new RetryListener() {\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic void onRetryPolicyExhaustion(RetryPolicy retryPolicy, Retryable<?> retryable, RetryException exception) {\n\t\t\t\t\t\t\trecoveryCallback.recover(null, exception);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tthis.retryTemplate.execute(() -> {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tthis.sendMessage(message);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (Exception e) {\n\t\t\t\t\t\t\treturn e;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.sendMessage(message);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\t\t\t\tlog.warn(\"consume message failed. messageExt:{}\", messageExt, e);\n\t\t\t\treturn failSupplier.get();\n\t\t\t}\n\t\t}\n\t\treturn sucSupplier.get();\n\t}\n\n\t@Override\n\tprotected void doStart() {\n\t\tif (extendedConsumerProperties.getExtension() == null\n\t\t\t\t|| !extendedConsumerProperties.getExtension().getEnabled()) {\n\t\t\treturn;\n\t\t}\n\t\tInstrumentation instrumentation = new Instrumentation(topic, this);\n\t\ttry {\n\t\t\tpushConsumer.subscribe(topic, RocketMQUtils.getMessageSelector(\n\t\t\t\t\textendedConsumerProperties.getExtension().getSubscription()));\n\t\t\tpushConsumer.start();\n\t\t\tinstrumentation.markStartedSuccessfully();\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tinstrumentation.markStartFailed(e);\n\t\t\tlog.error(\"DefaultMQPushConsumer init failed, Caused by \" + e.getMessage());\n\t\t\tthrow new MessagingException(MessageBuilder.withPayload(\n\t\t\t\t\t\"DefaultMQPushConsumer init failed, Caused by \" + e.getMessage())\n\t\t\t\t\t.build(), e);\n\t\t}\n\t\tfinally {\n\t\t\tInstrumentationManager.addHealthInstrumentation(instrumentation);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void doStop() {\n\t\tif (pushConsumer != null) {\n\t\t\tpushConsumer.shutdown();\n\t\t}\n\t}\n\n\tpublic void setRetryTemplate(RetryTemplate retryTemplate) {\n\t\tthis.retryTemplate = retryTemplate;\n\t}\n\n\tpublic void setRecoveryCallback(RecoveryCallback<Object> recoveryCallback) {\n\t\tthis.recoveryCallback = recoveryCallback;\n\t}\n\n\t@Override\n\tpublic int beforeShutdown() {\n\t\tthis.stop();\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic int afterShutdown() {\n\t\treturn 0;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/DefaultErrorAcknowledgeHandler.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.extend.ErrorAcknowledgeHandler;\n\nimport org.springframework.integration.acks.AcknowledgmentCallback.Status;\nimport org.springframework.messaging.Message;\n\n/**\n * By default, if consumption fails, the corresponding MessageQueue will always be\n * retried, that is, the consumption of other messages in the MessageQueue will be\n * blocked.\n *\n * @author zkzlx\n */\npublic class DefaultErrorAcknowledgeHandler implements ErrorAcknowledgeHandler {\n\n\t/**\n\t * Ack state handling, including receive, reject, and retry, when a consumption\n\t * exception occurs.\n\t * @param message message\n\t * @return see {@link Status}\n\t */\n\t@Override\n\tpublic Status handler(Message<?> message) {\n\t\treturn Status.REQUEUE;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull;\n\nimport java.util.Collections;\n\nimport org.apache.rocketmq.client.consumer.DefaultLitePullConsumer;\nimport org.apache.rocketmq.client.exception.MQClientException;\nimport org.apache.rocketmq.common.message.MessageExt;\nimport org.apache.rocketmq.common.message.MessageQueue;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.integration.acks.AcknowledgmentCallback;\nimport org.springframework.util.Assert;\n\n/**\n * A pollable {@link org.springframework.integration.core.MessageSource} for RocketMQ.\n *\n * @author zkzlx\n */\npublic class RocketMQAckCallback implements AcknowledgmentCallback {\n\n\tprivate final static Logger log = LoggerFactory.getLogger(RocketMQAckCallback.class);\n\n\tprivate boolean acknowledged;\n\n\tprivate boolean autoAckEnabled = true;\n\n\tprivate MessageExt messageExt;\n\n\tprivate DefaultLitePullConsumer consumer;\n\n\tprivate final MessageQueue messageQueue;\n\n\tpublic RocketMQAckCallback(DefaultLitePullConsumer consumer,\n\t\t\tMessageQueue messageQueue, MessageExt messageExt) {\n\t\tthis.messageExt = messageExt;\n\t\tthis.consumer = consumer;\n\t\tthis.messageQueue = messageQueue;\n\t}\n\n\t@Override\n\tpublic boolean isAcknowledged() {\n\t\treturn this.acknowledged;\n\t}\n\n\t@Override\n\tpublic void noAutoAck() {\n\t\tthis.autoAckEnabled = false;\n\t}\n\n\t@Override\n\tpublic boolean isAutoAck() {\n\t\treturn this.autoAckEnabled;\n\t}\n\n\t@Override\n\tpublic void acknowledge(Status status) {\n\t\tAssert.notNull(status, \"'status' cannot be null\");\n\t\tif (this.acknowledged) {\n\t\t\tthrow new IllegalStateException(\"Already acknowledged\");\n\t\t}\n\t\tsynchronized (messageQueue) {\n\t\t\ttry {\n\t\t\t\tlong offset = messageExt.getQueueOffset();\n\t\t\t\tswitch (status) {\n\t\t\t\tcase REJECT, ACCEPT -> consumer.commit(Collections.singleton(messageQueue), false);\n\t\t\t\tcase REQUEUE -> consumer.seek(messageQueue, offset);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (MQClientException e) {\n\t\t\t\tthrow new IllegalStateException(e);\n\t\t\t}\n\t\t\tfinally {\n\t\t\t\tthis.acknowledged = true;\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull;\n\nimport java.util.Collection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.RocketMQConsumerFactory;\nimport com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation;\nimport com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQMessageConverterSupport;\nimport com.alibaba.cloud.stream.binder.rocketmq.utils.RocketMQUtils;\nimport org.apache.rocketmq.client.consumer.DefaultLitePullConsumer;\nimport org.apache.rocketmq.client.consumer.MessageSelector;\nimport org.apache.rocketmq.client.exception.MQClientException;\nimport org.apache.rocketmq.common.message.MessageExt;\nimport org.apache.rocketmq.common.message.MessageQueue;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.beans.factory.DisposableBean;\nimport org.springframework.cloud.stream.binder.ExtendedConsumerProperties;\nimport org.springframework.context.Lifecycle;\nimport org.springframework.integration.IntegrationMessageHeaderAccessor;\nimport org.springframework.integration.endpoint.AbstractMessageSource;\nimport org.springframework.integration.support.MessageBuilder;\nimport org.springframework.messaging.Message;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.util.ObjectUtils;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class RocketMQMessageSource extends AbstractMessageSource<Object>\n\t\timplements DisposableBean, Lifecycle {\n\n\tprivate final static Logger log = LoggerFactory\n\t\t\t.getLogger(RocketMQMessageSource.class);\n\n\tprivate DefaultLitePullConsumer consumer;\n\n\tprivate final Map<String, Collection<MessageQueue>> messageQueuesForTopic = new ConcurrentHashMap<>();\n\n\tprivate volatile boolean running;\n\n\tprivate final String topic;\n\n\tprivate final MessageSelector messageSelector;\n\n\tprivate final ExtendedConsumerProperties<RocketMQConsumerProperties> extendedConsumerProperties;\n\n\tprivate volatile Iterator<MessageExt> messageExtIterator = null;\n\n\tpublic RocketMQMessageSource(String name,\n\t\t\tExtendedConsumerProperties<RocketMQConsumerProperties> extendedConsumerProperties) {\n\t\tthis.topic = name;\n\t\tthis.messageSelector = RocketMQUtils.getMessageSelector(\n\t\t\t\textendedConsumerProperties.getExtension().getSubscription());\n\t\tthis.extendedConsumerProperties = extendedConsumerProperties;\n\n\t}\n\n\t@Override\n\tpublic synchronized void start() {\n\t\tInstrumentation instrumentation = new Instrumentation(topic, this);\n\t\ttry {\n\t\t\tif (this.isRunning()) {\n\t\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\t\"pull consumer already running. \" + this.toString());\n\t\t\t}\n\t\t\tthis.consumer = RocketMQConsumerFactory\n\t\t\t\t\t.initPullConsumer(topic, extendedConsumerProperties);\n\t\t\t// This parameter must be 1, otherwise doReceive cannot be handled singly.\n\t\t\t// this.consumer.setPullBatchSize(1);\n\t\t\tthis.consumer.subscribe(topic, messageSelector);\n\t\t\tthis.consumer.setAutoCommit(false);\n\t\t\t// register TopicMessageQueueChangeListener for messageQueuesForTopic\n\t\t\tconsumer.registerTopicMessageQueueChangeListener(topic,\n\t\t\t\t\tmessageQueuesForTopic::put);\n\t\t\tthis.consumer.start();\n\t\t\t// Initialize messageQueuesForTopic immediately\n\t\t\tmessageQueuesForTopic.put(topic, consumer.fetchMessageQueues(topic));\n\t\t\tinstrumentation.markStartedSuccessfully();\n\t\t}\n\t\tcatch (MQClientException e) {\n\t\t\tinstrumentation.markStartFailed(e);\n\t\t\tlog.error(\"DefaultMQPullConsumer startup error: \" + e.getMessage(), e);\n\t\t}\n\t\tfinally {\n\t\t\tInstrumentationManager.addHealthInstrumentation(instrumentation);\n\t\t}\n\t\tthis.running = true;\n\t}\n\n\tprivate MessageQueue acquireCurrentMessageQueue(String topic, int queueId,\n\t\t\tString brokerName) {\n\t\tCollection<MessageQueue> messageQueueSet = messageQueuesForTopic.get(topic);\n\t\tif (CollectionUtils.isEmpty(messageQueueSet)) {\n\t\t\treturn null;\n\t\t}\n\t\tfor (MessageQueue messageQueue : messageQueueSet) {\n\t\t\tif (messageQueue.getQueueId() == queueId && ObjectUtils\n\t\t\t\t\t.nullSafeEquals(brokerName, messageQueue.getBrokerName())) {\n\t\t\t\treturn messageQueue;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic synchronized void stop() {\n\t\tif (this.isRunning() && null != consumer) {\n\t\t\tconsumer.unsubscribe(topic);\n\t\t\tconsumer.shutdown();\n\t\t\tthis.running = false;\n\t\t}\n\t}\n\n\t@Override\n\tpublic synchronized boolean isRunning() {\n\t\treturn running;\n\t}\n\n\t@Override\n\tprotected synchronized Object doReceive() {\n\t\tif (messageExtIterator == null) {\n\t\t\tList<MessageExt> messageExtList = consumer.poll();\n\t\t\tif (CollectionUtils.isEmpty(messageExtList)) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tmessageExtIterator = messageExtList.iterator();\n\t\t}\n\t\tMessageExt messageExt = messageExtIterator.next();\n\t\tif (!messageExtIterator.hasNext()) {\n\t\t\tmessageExtIterator = null;\n\t\t}\n\t\tif (null == messageExt) {\n\t\t\treturn null;\n\t\t}\n\t\tMessageQueue messageQueue = this.acquireCurrentMessageQueue(messageExt.getTopic(),\n\t\t\t\tmessageExt.getQueueId(), messageExt.getBrokerName());\n\t\tif (messageQueue == null) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"The message queue is not in assigned list\");\n\t\t}\n\t\tMessage message = RocketMQMessageConverterSupport\n\t\t\t\t.convertMessage2Spring(messageExt);\n\t\treturn MessageBuilder.fromMessage(message)\n\t\t\t\t.setHeader(IntegrationMessageHeaderAccessor.ACKNOWLEDGMENT_CALLBACK,\n\t\t\t\t\t\tnew RocketMQAckCallback(this.consumer, messageQueue, messageExt))\n\t\t\t\t.build();\n\t}\n\n\t@Override\n\tpublic String getComponentType() {\n\t\treturn \"rocketmq:message-source\";\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.integration.outbound;\n\nimport java.lang.reflect.Field;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.constant.RocketMQConst;\nimport com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQBeanContainerCache;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.utils.RocketMQUtils;\nimport org.apache.rocketmq.acl.common.AclClientRPCHook;\nimport org.apache.rocketmq.acl.common.SessionCredentials;\nimport org.apache.rocketmq.client.AccessChannel;\nimport org.apache.rocketmq.client.hook.CheckForbiddenHook;\nimport org.apache.rocketmq.client.hook.SendMessageHook;\nimport org.apache.rocketmq.client.producer.DefaultMQProducer;\nimport org.apache.rocketmq.client.producer.TransactionMQProducer;\nimport org.apache.rocketmq.client.trace.AsyncTraceDispatcher;\nimport org.apache.rocketmq.client.trace.TraceDispatcher;\nimport org.apache.rocketmq.client.trace.hook.SendMessageTraceHookImpl;\nimport org.apache.rocketmq.common.UtilAll;\nimport org.apache.rocketmq.remoting.RPCHook;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.util.Assert;\nimport org.springframework.util.StringUtils;\n\n/**\n * Extended function related to producer . eg:initial .\n *\n * @author zkzlx\n */\npublic final class RocketMQProduceFactory {\n\n\tprivate RocketMQProduceFactory() {\n\t}\n\n\tprivate final static Logger log = LoggerFactory\n\t\t\t.getLogger(RocketMQProduceFactory.class);\n\n\t/**\n\t * init for the producer,including convert producer params.\n\t * @param topic topic\n\t * @param producerProperties producerProperties\n\t * @return DefaultMQProducer\n\t */\n\tpublic static DefaultMQProducer initRocketMQProducer(String topic,\n\t\t\tRocketMQProducerProperties producerProperties) {\n\t\tif (!StringUtils.hasLength(producerProperties.getGroup())) {\n\t\t\tproducerProperties.setGroup(RocketMQConst.DEFAULT_GROUP);\n\t\t}\n\n\t\tAssert.notNull(producerProperties.getNameServer(),\n\t\t\t\t\"Property 'nameServer' is required\");\n\n\t\tRPCHook rpcHook = null;\n\t\tif (StringUtils.hasLength(producerProperties.getAccessKey())\n\t\t\t\t&& StringUtils.hasLength(producerProperties.getSecretKey())) {\n\t\t\trpcHook = new AclClientRPCHook(\n\t\t\t\t\tnew SessionCredentials(producerProperties.getAccessKey(),\n\t\t\t\t\t\t\tproducerProperties.getSecretKey()));\n\t\t}\n\t\tDefaultMQProducer producer;\n\t\tif (RocketMQProducerProperties.ProducerType.Trans\n\t\t\t\t.equalsName(producerProperties.getProducerType())) {\n\t\t\tproducer = new TransactionMQProducer(producerProperties.getNamespace(),\n\t\t\t\t\tproducerProperties.getGroup(), rpcHook, producerProperties.getEnableMsgTrace(),\n\t\t\t\t\tproducerProperties.getCustomizedTraceTopic());\n\t\t\tif (producerProperties.getEnableMsgTrace()) {\n\t\t\t\ttry {\n\t\t\t\t\tAsyncTraceDispatcher dispatcher = new AsyncTraceDispatcher(\n\t\t\t\t\t\t\tproducerProperties.getGroup(), TraceDispatcher.Type.PRODUCE, 10,\n\t\t\t\t\t\t\tproducerProperties.getCustomizedTraceTopic(), rpcHook);\n\t\t\t\t\tdispatcher.setHostProducer(producer.getDefaultMQProducerImpl());\n\t\t\t\t\tField field = DefaultMQProducer.class\n\t\t\t\t\t\t\t.getDeclaredField(\"traceDispatcher\");\n\t\t\t\t\tfield.setAccessible(true);\n\t\t\t\t\tfield.set(producer, dispatcher);\n\t\t\t\t\tproducer.getDefaultMQProducerImpl().registerSendMessageHook(\n\t\t\t\t\t\t\tnew SendMessageTraceHookImpl(dispatcher));\n\t\t\t\t}\n\t\t\t\tcatch (Throwable e) {\n\t\t\t\t\tlog.error(\n\t\t\t\t\t\t\t\"system mq-trace hook init failed ,maybe can't send msg trace data\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tproducer = new DefaultMQProducer(producerProperties.getNamespace(),\n\t\t\t\t\tproducerProperties.getGroup(), rpcHook,\n\t\t\t\t\tproducerProperties.getEnableMsgTrace(),\n\t\t\t\t\tproducerProperties.getCustomizedTraceTopic());\n\t\t}\n\n\t\tproducer.setVipChannelEnabled(\n\t\t\t\tnull == rpcHook && producerProperties.getVipChannelEnabled());\n\t\tproducer.setInstanceName(\n\t\t\t\tRocketMQUtils.getInstanceName(rpcHook, topic + \"|\" + UtilAll.getPid()));\n\t\tproducer.setNamesrvAddr(producerProperties.getNameServer());\n\t\tproducer.setNamespaceV2(producerProperties.getNamespaceV2());\n\t\tproducer.setSendMsgTimeout(producerProperties.getSendMsgTimeout());\n\t\tproducer.setRetryTimesWhenSendFailed(\n\t\t\t\tproducerProperties.getRetryTimesWhenSendFailed());\n\t\tproducer.setRetryTimesWhenSendAsyncFailed(\n\t\t\t\tproducerProperties.getRetryTimesWhenSendAsyncFailed());\n\t\tproducer.setCompressMsgBodyOverHowmuch(\n\t\t\t\tproducerProperties.getCompressMsgBodyThreshold());\n\t\tproducer.setRetryAnotherBrokerWhenNotStoreOK(\n\t\t\t\tproducerProperties.getRetryAnotherBroker());\n\t\tproducer.setMaxMessageSize(producerProperties.getMaxMessageSize());\n\t\tproducer.setUseTLS(producerProperties.getUseTLS());\n\t\tproducer.setUnitName(producerProperties.getUnitName());\n\t\tproducer.setAccessChannel(AccessChannel.valueOf(producerProperties.getAccessChannel()));\n\t\tCheckForbiddenHook checkForbiddenHook = RocketMQBeanContainerCache.getBean(\n\t\t\t\tproducerProperties.getCheckForbiddenHook(), CheckForbiddenHook.class);\n\t\tif (null != checkForbiddenHook) {\n\t\t\tproducer.getDefaultMQProducerImpl()\n\t\t\t\t\t.registerCheckForbiddenHook(checkForbiddenHook);\n\t\t}\n\t\tSendMessageHook sendMessageHook = RocketMQBeanContainerCache\n\t\t\t\t.getBean(producerProperties.getSendMessageHook(), SendMessageHook.class);\n\t\tif (null != sendMessageHook) {\n\t\t\tproducer.getDefaultMQProducerImpl().registerSendMessageHook(sendMessageHook);\n\t\t}\n\n\t\treturn producer;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.integration.outbound;\n\nimport java.util.List;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.constant.RocketMQConst;\nimport com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQBeanContainerCache;\nimport com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation;\nimport com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.provisioning.selector.PartitionMessageQueueSelector;\nimport com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQMessageConverterSupport;\nimport org.apache.rocketmq.client.exception.MQBrokerException;\nimport org.apache.rocketmq.client.exception.MQClientException;\nimport org.apache.rocketmq.client.producer.DefaultMQProducer;\nimport org.apache.rocketmq.client.producer.MessageQueueSelector;\nimport org.apache.rocketmq.client.producer.SendCallback;\nimport org.apache.rocketmq.client.producer.SendResult;\nimport org.apache.rocketmq.client.producer.SendStatus;\nimport org.apache.rocketmq.client.producer.TransactionListener;\nimport org.apache.rocketmq.client.producer.TransactionMQProducer;\nimport org.apache.rocketmq.common.message.MessageQueue;\nimport org.apache.rocketmq.remoting.exception.RemotingException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.cloud.stream.binder.ExtendedProducerProperties;\nimport org.springframework.cloud.stream.binding.MessageConverterConfigurer;\nimport org.springframework.cloud.stream.binding.MessageConverterConfigurer.PartitioningInterceptor;\nimport org.springframework.cloud.stream.provisioning.ProducerDestination;\nimport org.springframework.context.Lifecycle;\nimport org.springframework.integration.handler.AbstractMessageHandler;\nimport org.springframework.integration.support.ErrorMessageStrategy;\nimport org.springframework.integration.support.ErrorMessageUtils;\nimport org.springframework.messaging.Message;\nimport org.springframework.messaging.MessageChannel;\nimport org.springframework.messaging.MessagingException;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class RocketMQProducerMessageHandler extends AbstractMessageHandler\n\t\timplements Lifecycle {\n\n\tprivate final static Logger log = LoggerFactory\n\t\t\t.getLogger(RocketMQProducerMessageHandler.class);\n\n\tprivate volatile boolean running = false;\n\n\tprivate volatile boolean isTrans = false;\n\n\tprivate ErrorMessageStrategy errorMessageStrategy;\n\n\tprivate MessageChannel sendFailureChannel;\n\n\tprivate MessageConverterConfigurer.PartitioningInterceptor partitioningInterceptor;\n\n\tprivate DefaultMQProducer defaultMQProducer;\n\n\tprivate MessageQueueSelector messageQueueSelector;\n\n\tprivate final ProducerDestination destination;\n\n\tprivate final ExtendedProducerProperties<RocketMQProducerProperties> extendedProducerProperties;\n\n\tprivate final RocketMQProducerProperties mqProducerProperties;\n\n\tpublic RocketMQProducerMessageHandler(ProducerDestination destination,\n\t\t\tExtendedProducerProperties<RocketMQProducerProperties> extendedProducerProperties,\n\t\t\tRocketMQProducerProperties mqProducerProperties) {\n\t\tthis.destination = destination;\n\t\tthis.extendedProducerProperties = extendedProducerProperties;\n\t\tthis.mqProducerProperties = mqProducerProperties;\n\t}\n\n\t@Override\n\tprotected void onInit() {\n\t\tif (null == mqProducerProperties || !mqProducerProperties.getEnabled()) {\n\t\t\treturn;\n\t\t}\n\t\tsuper.onInit();\n\t\tthis.defaultMQProducer = RocketMQProduceFactory\n\t\t\t\t.initRocketMQProducer(destination.getName(), mqProducerProperties);\n\t\tthis.isTrans = defaultMQProducer instanceof TransactionMQProducer;\n\t\t// Use the default if the partition is on and no customization is available.\n\t\tthis.messageQueueSelector = RocketMQBeanContainerCache.getBean(\n\t\t\t\tmqProducerProperties.getMessageQueueSelector(),\n\t\t\t\tMessageQueueSelector.class,\n\t\t\t\textendedProducerProperties.isPartitioned()\n\t\t\t\t\t\t? new PartitionMessageQueueSelector()\n\t\t\t\t\t\t: null);\n\t}\n\n\t@Override\n\tpublic void start() {\n\t\tInstrumentation instrumentation = new Instrumentation(destination.getName(),\n\t\t\t\tthis);\n\t\ttry {\n\t\t\tdefaultMQProducer.start();\n\t\t\t// TransactionMQProducer does not currently support custom\n\t\t\t// MessageQueueSelector.\n\t\t\tif (!isTrans && extendedProducerProperties.isPartitioned()) {\n\t\t\t\tList<MessageQueue> messageQueues = defaultMQProducer\n\t\t\t\t\t\t.fetchPublishMessageQueues(destination.getName());\n\t\t\t\tif (extendedProducerProperties.getPartitionCount() != messageQueues\n\t\t\t\t\t\t.size()) {\n\t\t\t\t\tlog.info(String.format(\n\t\t\t\t\t\t\t\"The partition count of topic '%s' will change from '%s' to '%s'\",\n\t\t\t\t\t\t\tdestination.getName(),\n\t\t\t\t\t\t\textendedProducerProperties.getPartitionCount(),\n\t\t\t\t\t\t\tmessageQueues.size()));\n\t\t\t\t\textendedProducerProperties.setPartitionCount(messageQueues.size());\n\t\t\t\t\t// may be npe!\n\t\t\t\t\tpartitioningInterceptor.setPartitionCount(\n\t\t\t\t\t\t\textendedProducerProperties.getPartitionCount());\n\t\t\t\t}\n\t\t\t}\n\t\t\trunning = true;\n\t\t\tinstrumentation.markStartedSuccessfully();\n\t\t}\n\t\tcatch (MQClientException | NullPointerException e) {\n\t\t\tinstrumentation.markStartFailed(e);\n\t\t\tlog.error(\"The defaultMQProducer startup failure !!!\", e);\n\t\t}\n\t\tfinally {\n\t\t\tInstrumentationManager.addHealthInstrumentation(instrumentation);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void stop() {\n\t\tif (running && null != defaultMQProducer) {\n\t\t\tdefaultMQProducer.shutdown();\n\t\t}\n\t\trunning = false;\n\t}\n\n\t@Override\n\tpublic boolean isRunning() {\n\t\treturn running;\n\t}\n\n\t@Override\n\tprotected void handleMessageInternal(Message<?> message) {\n\t\ttry {\n\t\t\torg.apache.rocketmq.common.message.Message mqMessage = RocketMQMessageConverterSupport\n\t\t\t\t\t.convertMessage2MQ(destination.getName(), message);\n\t\t\tSendResult sendResult;\n\t\t\tif (defaultMQProducer instanceof TransactionMQProducer translateMQProducer) {\n\t\t\t\tTransactionListener transactionListener = RocketMQBeanContainerCache\n\t\t\t\t\t\t.getBean(mqProducerProperties.getTransactionListener(),\n\t\t\t\t\t\t\t\tTransactionListener.class);\n\t\t\t\tif (transactionListener == null) {\n\t\t\t\t\tthrow new MessagingException(\n\t\t\t\t\t\t\t\"TransactionMQProducer must have a TransactionListener !!! \");\n\t\t\t\t}\n\t\t\t\ttranslateMQProducer.setTransactionListener(transactionListener);\n\t\t\t\tif (log.isDebugEnabled()) {\n\t\t\t\t\tlog.debug(\"send transaction message ->{}\", mqMessage);\n\t\t\t\t}\n\t\t\t\tsendResult = defaultMQProducer.sendMessageInTransaction(mqMessage,\n\t\t\t\t\t\tmessage.getHeaders().get(RocketMQConst.USER_TRANSACTIONAL_ARGS));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (log.isDebugEnabled()) {\n\t\t\t\t\tlog.debug(\"send message ->{}\", mqMessage);\n\t\t\t\t}\n\t\t\t\tsendResult = this.send(mqMessage, this.messageQueueSelector,\n\t\t\t\t\t\tmessage.getHeaders(), message);\n\t\t\t}\n\t\t\tif (log.isDebugEnabled()) {\n\t\t\t\tlog.debug(\"the message has sent,message={},sendResult={}\", mqMessage,\n\t\t\t\t\t\tsendResult);\n\t\t\t}\n\t\t\tif (sendResult == null\n\t\t\t\t\t|| !SendStatus.SEND_OK.equals(sendResult.getSendStatus())) {\n\t\t\t\tlog.error(\"message send fail.SendStatus is not OK.the message={}\",\n\t\t\t\t\t\tmqMessage);\n\t\t\t\tthis.doFail(message, new MessagingException(\n\t\t\t\t\t\t\"message send fail.SendStatus is not OK.\"));\n\t\t\t}\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tlog.error(\"RocketMQ Message hasn't been sent. Caused by \" + e.getMessage(),\n\t\t\t\t\te);\n\t\t\tthis.doFail(message, e);\n\t\t}\n\t}\n\n\tprivate SendResult send(org.apache.rocketmq.common.message.Message mqMessage,\n\t\t\tMessageQueueSelector selector, Object args, Message<?> message)\n\t\t\tthrows RemotingException, MQClientException, InterruptedException,\n\t\t\tMQBrokerException {\n\t\tSendResult sendResult = new SendResult();\n\t\tsendResult.setSendStatus(SendStatus.SEND_OK);\n\t\tif (RocketMQProducerProperties.SendType.OneWay\n\t\t\t\t.equalsName(mqProducerProperties.getSendType())) {\n\t\t\tif (null != selector) {\n\t\t\t\tdefaultMQProducer.sendOneway(mqMessage, selector, args);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tdefaultMQProducer.sendOneway(mqMessage);\n\t\t\t}\n\t\t\treturn sendResult;\n\t\t}\n\t\tif (RocketMQProducerProperties.SendType.Sync\n\t\t\t\t.equalsName(mqProducerProperties.getSendType())) {\n\t\t\tif (null != selector) {\n\t\t\t\treturn defaultMQProducer.send(mqMessage, selector, args);\n\t\t\t}\n\t\t\treturn defaultMQProducer.send(mqMessage);\n\t\t}\n\t\tif (RocketMQProducerProperties.SendType.Async\n\t\t\t\t.equalsName(mqProducerProperties.getSendType())) {\n\t\t\tif (null != selector) {\n\t\t\t\tdefaultMQProducer.send(mqMessage, selector, args,\n\t\t\t\t\t\tthis.getSendCallback(message));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tdefaultMQProducer.send(mqMessage, this.getSendCallback(message));\n\t\t\t}\n\t\t\treturn sendResult;\n\t\t}\n\t\tthrow new MessagingException(\n\t\t\t\t\"message hasn't been sent,cause by : the SendType must be in this values[OneWay, Async, Sync]\");\n\t}\n\n\t/**\n\t * https://github.com/alibaba/spring-cloud-alibaba/issues/1408 .\n\t * @param message message\n\t * @return SendCallback\n\t */\n\tprivate SendCallback getSendCallback(Message<?> message) {\n\t\tSendCallback sendCallback = RocketMQBeanContainerCache\n\t\t\t\t.getBean(mqProducerProperties.getSendCallBack(), SendCallback.class);\n\t\tif (null == sendCallback) {\n\t\t\tsendCallback = new SendCallback() {\n\t\t\t\t@Override\n\t\t\t\tpublic void onSuccess(SendResult sendResult) {\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void onException(Throwable e) {\n\t\t\t\t\tRocketMQProducerMessageHandler.this.doFail(message, e);\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\treturn sendCallback;\n\t}\n\n\tprivate void doFail(Message<?> message, Throwable e) {\n\t\tif (getSendFailureChannel() != null) {\n\t\t\tgetSendFailureChannel().send(getErrorMessageStrategy().buildErrorMessage(e,\n\t\t\t\t\tErrorMessageUtils.getAttributeAccessor(message, message)));\n\t\t}\n\t\telse {\n\t\t\tthrow new MessagingException(message, e);\n\t\t}\n\t}\n\n\tpublic MessageChannel getSendFailureChannel() {\n\t\treturn sendFailureChannel;\n\t}\n\n\tpublic void setSendFailureChannel(MessageChannel sendFailureChannel) {\n\t\tthis.sendFailureChannel = sendFailureChannel;\n\t}\n\n\tpublic ErrorMessageStrategy getErrorMessageStrategy() {\n\t\treturn errorMessageStrategy;\n\t}\n\n\tpublic void setErrorMessageStrategy(ErrorMessageStrategy errorMessageStrategy) {\n\t\tthis.errorMessageStrategy = errorMessageStrategy;\n\t}\n\n\tpublic PartitioningInterceptor getPartitioningInterceptor() {\n\t\treturn partitioningInterceptor;\n\t}\n\n\tpublic RocketMQProducerMessageHandler setPartitioningInterceptor(\n\t\t\tPartitioningInterceptor partitioningInterceptor) {\n\t\tthis.partitioningInterceptor = partitioningInterceptor;\n\t\treturn this;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/Instrumentation.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.metrics;\n\nimport java.util.Objects;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport org.springframework.context.Lifecycle;\n\n/**\n * @author Timur Valiev\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class Instrumentation {\n\n\tprivate final String name;\n\n\tprivate Lifecycle actuator;\n\n\tprotected final AtomicBoolean started = new AtomicBoolean(false);\n\n\tprotected Exception startException = null;\n\n\tpublic Instrumentation(String name) {\n\t\tthis.name = name;\n\t}\n\n\tpublic Instrumentation(String name, Lifecycle actuator) {\n\t\tthis.name = name;\n\t\tthis.actuator = actuator;\n\t}\n\n\tpublic Lifecycle getActuator() {\n\t\treturn actuator;\n\t}\n\n\tpublic void setActuator(Lifecycle actuator) {\n\t\tthis.actuator = actuator;\n\t}\n\n\tpublic boolean isDown() {\n\t\treturn startException != null;\n\t}\n\n\tpublic boolean isUp() {\n\t\treturn started.get();\n\t}\n\n\tpublic boolean isOutOfService() {\n\t\treturn !started.get() && startException == null;\n\t}\n\n\tpublic void markStartedSuccessfully() {\n\t\tstarted.set(true);\n\t}\n\n\tpublic void markStartFailed(Exception e) {\n\t\tstarted.set(false);\n\t\tstartException = e;\n\t}\n\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\tpublic boolean isStarted() {\n\t\treturn started.get();\n\t}\n\n\tpublic Exception getStartException() {\n\t\treturn startException;\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn Objects.hash(getName(), getActuator());\n\t}\n\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (this == o) {\n\t\t\treturn true;\n\t\t}\n\t\tif (o == null || getClass() != o.getClass()) {\n\t\t\treturn false;\n\t\t}\n\t\tInstrumentation that = (Instrumentation) o;\n\t\treturn name.equals(that.name) && actuator.equals(that.actuator);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/InstrumentationManager.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.metrics;\n\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * @author Timur Valiev\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic final class InstrumentationManager {\n\n\tprivate InstrumentationManager() {\n\t}\n\n\tprivate static final Map<Integer, Instrumentation> HEALTH_INSTRUMENTATIONS = new HashMap<>();\n\n\tpublic static Collection<Instrumentation> getHealthInstrumentations() {\n\t\treturn HEALTH_INSTRUMENTATIONS.values();\n\t}\n\n\tpublic static void addHealthInstrumentation(Instrumentation instrumentation) {\n\t\tif (null != instrumentation) {\n\t\t\tHEALTH_INSTRUMENTATIONS.computeIfPresent(instrumentation.hashCode(),\n\t\t\t\t\t(k, v) -> {\n\t\t\t\t\t\tif (instrumentation.getActuator() != null) {\n\t\t\t\t\t\t\tinstrumentation.getActuator().stop();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\t\t\"The current actuator exists, please confirm if there is a repeat operation!!!\");\n\t\t\t\t\t});\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.properties;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\n\n/**\n * binding rocketMq properties.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@ConfigurationProperties(prefix = \"spring.cloud.stream.rocketmq.binder\")\npublic class RocketMQBinderConfigurationProperties extends RocketMQCommonProperties {\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.properties;\n\nimport java.io.Serializable;\n\nimport org.apache.rocketmq.client.AccessChannel;\nimport org.apache.rocketmq.client.impl.factory.MQClientInstance;\nimport org.apache.rocketmq.remoting.netty.TlsSystemConfig;\n\n/**\n * @author zkzlx\n */\npublic class RocketMQCommonProperties implements Serializable {\n\n\tprivate static final long serialVersionUID = -6724870154343284715L;\n\n\tprivate boolean enabled = true;\n\n\tprivate String nameServer;\n\n\t/**\n\t * The property of \"access-key\".\n\t */\n\tprivate String accessKey;\n\n\t/**\n\t * The property of \"secret-key\".\n\t */\n\tprivate String secretKey;\n\n\t/**\n\t * Consumers of the same role is required to have exactly same subscriptions and\n\t * consumerGroup to correctly achieve load balance. It's required and needs to be\n\t * globally unique. Producer group conceptually aggregates all producer instances of\n\t * exactly same role, which is particularly important when transactional messages are\n\t * involved. For non-transactional messages, it does not matter as long as it's unique\n\t * per process. See <a href=\"http://rocketmq.apache.org/docs/core-concept/\">here</a>\n\t * for further discussion.\n\t */\n\tprivate String group;\n\n\tprivate String namespace;\n\n\tprivate String namespaceV2;\n\n\t/**\n\t * The property of \"unitName\".\n\t */\n\tprivate String unitName;\n\n\tprivate String accessChannel = AccessChannel.LOCAL.name();\n\n\t/**\n\t * Pulling topic information interval from the named server.\n\t * see{@link MQClientInstance#startScheduledTask()},eg:ScheduledTask\n\t * updateTopicRouteInfoFromNameServer.\n\t */\n\tprivate int pollNameServerInterval = 1000 * 30;\n\n\t/**\n\t * Heartbeat interval in microseconds with message broker.\n\t * see{@link MQClientInstance#startScheduledTask()},eg:ScheduledTask\n\t * sendHeartbeatToAllBroker .\n\t */\n\tprivate int heartbeatBrokerInterval = 1000 * 30;\n\n\t/**\n\t * Offset persistent interval for consumer.\n\t * see{@link MQClientInstance#startScheduledTask()},eg:ScheduledTask\n\t * sendHeartbeatToAllBroker .\n\t */\n\tprivate int persistConsumerOffsetInterval = 1000 * 5;\n\n\tprivate boolean vipChannelEnabled = false;\n\n\tprivate boolean useTLS = TlsSystemConfig.tlsEnable;\n\n\tprivate boolean enableMsgTrace = true;\n\n\tprivate String customizedTraceTopic;\n\n\tpublic boolean getEnabled() {\n\t\treturn enabled;\n\t}\n\n\tpublic void setEnabled(boolean enabled) {\n\t\tthis.enabled = enabled;\n\t}\n\n\tpublic String getNameServer() {\n\t\treturn nameServer;\n\t}\n\n\tpublic void setNameServer(String nameServer) {\n\t\tthis.nameServer = nameServer;\n\t}\n\n\tpublic String getAccessKey() {\n\t\treturn accessKey;\n\t}\n\n\tpublic void setAccessKey(String accessKey) {\n\t\tthis.accessKey = accessKey;\n\t}\n\n\tpublic String getSecretKey() {\n\t\treturn secretKey;\n\t}\n\n\tpublic void setSecretKey(String secretKey) {\n\t\tthis.secretKey = secretKey;\n\t}\n\n\tpublic String getGroup() {\n\t\treturn group;\n\t}\n\n\tpublic void setGroup(String group) {\n\t\tthis.group = group;\n\t}\n\n\tpublic String getNamespace() {\n\t\treturn namespace;\n\t}\n\n\tpublic void setNamespace(String namespace) {\n\t\tthis.namespace = namespace;\n\t}\n\n\tpublic String getNamespaceV2() {\n\t\treturn namespaceV2;\n\t}\n\n\tpublic void setNamespaceV2(String namespaceV2) {\n\t\tthis.namespaceV2 = namespaceV2;\n\t}\n\n\tpublic String getAccessChannel() {\n\t\treturn accessChannel;\n\t}\n\n\tpublic void setAccessChannel(String accessChannel) {\n\t\tthis.accessChannel = accessChannel;\n\t}\n\n\tpublic int getPollNameServerInterval() {\n\t\treturn pollNameServerInterval;\n\t}\n\n\tpublic void setPollNameServerInterval(int pollNameServerInterval) {\n\t\tthis.pollNameServerInterval = pollNameServerInterval;\n\t}\n\n\tpublic int getHeartbeatBrokerInterval() {\n\t\treturn heartbeatBrokerInterval;\n\t}\n\n\tpublic void setHeartbeatBrokerInterval(int heartbeatBrokerInterval) {\n\t\tthis.heartbeatBrokerInterval = heartbeatBrokerInterval;\n\t}\n\n\tpublic int getPersistConsumerOffsetInterval() {\n\t\treturn persistConsumerOffsetInterval;\n\t}\n\n\tpublic void setPersistConsumerOffsetInterval(int persistConsumerOffsetInterval) {\n\t\tthis.persistConsumerOffsetInterval = persistConsumerOffsetInterval;\n\t}\n\n\tpublic boolean getVipChannelEnabled() {\n\t\treturn vipChannelEnabled;\n\t}\n\n\tpublic void setVipChannelEnabled(boolean vipChannelEnabled) {\n\t\tthis.vipChannelEnabled = vipChannelEnabled;\n\t}\n\n\tpublic boolean getUseTLS() {\n\t\treturn useTLS;\n\t}\n\n\tpublic void setUseTLS(boolean useTLS) {\n\t\tthis.useTLS = useTLS;\n\t}\n\n\tpublic boolean getEnableMsgTrace() {\n\t\treturn enableMsgTrace;\n\t}\n\n\tpublic void setEnableMsgTrace(boolean enableMsgTrace) {\n\t\tthis.enableMsgTrace = enableMsgTrace;\n\t}\n\n\tpublic String getCustomizedTraceTopic() {\n\t\treturn customizedTraceTopic;\n\t}\n\n\tpublic void setCustomizedTraceTopic(String customizedTraceTopic) {\n\t\tthis.customizedTraceTopic = customizedTraceTopic;\n\t}\n\n\tpublic String getUnitName() {\n\t\treturn unitName;\n\t}\n\n\tpublic void setUnitName(String unitName) {\n\t\tthis.unitName = unitName;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQConsumerProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.properties;\n\nimport java.io.Serializable;\n\nimport org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;\nimport org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext;\nimport org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;\nimport org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly;\nimport org.apache.rocketmq.client.impl.consumer.ConsumeMessageConcurrentlyService;\nimport org.apache.rocketmq.client.impl.consumer.ConsumeMessageOrderlyService;\nimport org.apache.rocketmq.common.UtilAll;\nimport org.apache.rocketmq.common.consumer.ConsumeFromWhere;\nimport org.apache.rocketmq.remoting.protocol.heartbeat.MessageModel;\n\n/**\n * Extended consumer properties for RocketMQ binder.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class RocketMQConsumerProperties extends RocketMQCommonProperties {\n\n\t/**\n\t * Message model defines the way how messages are delivered to each consumer clients.\n\t * This field defaults to clustering.\n\t */\n\tprivate String messageModel = MessageModel.CLUSTERING.getModeCN();\n\n\t/**\n\t * Queue allocation algorithm specifying how message queues are allocated to each\n\t * consumer clients.\n\t */\n\tprivate String allocateMessageQueueStrategy;\n\n\t/**\n\t * The expressions include tags or SQL,as follow:\n\t * <p>\n\t * tag: {@code tag1||tag2||tag3 }; sql: {@code 'color'='blue' AND 'price'>100 } .\n\t * </p>\n\t * Determines whether there are specific characters \"{@code ||}\" in the expression to\n\t * determine how the message is filtered,tags or SQL.\n\t */\n\tprivate String subscription;\n\n\t/**\n\t * Delay some time when exception occur .\n\t */\n\tprivate long pullTimeDelayMillsWhenException = 1000;\n\n\t/**\n\t * Consuming point on consumer booting.\n\t *\n\t * There are three consuming points:\n\t * <ul>\n\t * <li><code>CONSUME_FROM_LAST_OFFSET</code>: consumer clients pick up where it\n\t * stopped previously. If it were a newly booting up consumer client, according aging\n\t * of the consumer group, there are two cases:\n\t * <ol>\n\t * <li>if the consumer group is created so recently that the earliest message being\n\t * subscribed has yet expired, which means the consumer group represents a lately\n\t * launched business, consuming will start from the very beginning;</li>\n\t * <li>if the earliest message being subscribed has expired, consuming will start from\n\t * the latest messages, meaning messages born prior to the booting timestamp would be\n\t * ignored.</li>\n\t * </ol>\n\t * </li>\n\t * <li><code>CONSUME_FROM_FIRST_OFFSET</code>: Consumer client will start from\n\t * earliest messages available.</li>\n\t * <li><code>CONSUME_FROM_TIMESTAMP</code>: Consumer client will start from specified\n\t * timestamp, which means messages born prior to {@link #consumeTimestamp} will be\n\t * ignored</li>\n\t * </ul>\n\t */\n\tprivate ConsumeFromWhere consumeFromWhere = ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET;\n\n\t/**\n\t * Backtracking consumption time with second precision. Time format is\n\t * 20131223171201<br>\n\t * Implying Seventeen twelve and 01 seconds on December 23, 2013 year<br>\n\t * Default backtracking consumption time Half an hour ago.\n\t */\n\tprivate String consumeTimestamp = UtilAll\n\t\t\t.timeMillisToHumanString3(System.currentTimeMillis() - (1000 * 60 * 30));\n\n\t/**\n\t * Flow control threshold on queue level, each message queue will cache at most 1000\n\t * messages by default, Consider the {@link #pullBatchSize}, the instantaneous value\n\t * may exceed the limit .\n\t */\n\tprivate int pullThresholdForQueue = 1000;\n\n\t/**\n\t * Limit the cached message size on queue level, each message queue will cache at most\n\t * 100 MiB messages by default, Consider the {@link #pullBatchSize}, the instantaneous\n\t * value may exceed the limit .\n\t *\n\t * <p>\n\t * The size of a message only measured by message body, so it's not accurate\n\t */\n\tprivate int pullThresholdSizeForQueue = 100;\n\n\t/**\n\t * Maximum number of messages pulled each time.\n\t */\n\tprivate int pullBatchSize = 10;\n\n\t/**\n\t * Consume max span offset.it has no effect on sequential consumption.\n\t */\n\tprivate int consumeMaxSpan = 2000;\n\n\tprivate Push push = new Push();\n\n\tprivate Pull pull = new Pull();\n\n\tpublic String getMessageModel() {\n\t\treturn messageModel;\n\t}\n\n\tpublic RocketMQConsumerProperties setMessageModel(String messageModel) {\n\t\tthis.messageModel = messageModel;\n\t\treturn this;\n\t}\n\n\tpublic String getAllocateMessageQueueStrategy() {\n\t\treturn allocateMessageQueueStrategy;\n\t}\n\n\tpublic void setAllocateMessageQueueStrategy(String allocateMessageQueueStrategy) {\n\t\tthis.allocateMessageQueueStrategy = allocateMessageQueueStrategy;\n\t}\n\n\tpublic String getSubscription() {\n\t\treturn subscription;\n\t}\n\n\tpublic void setSubscription(String subscription) {\n\t\tthis.subscription = subscription;\n\t}\n\n\tpublic Push getPush() {\n\t\treturn push;\n\t}\n\n\tpublic void setPush(Push push) {\n\t\tthis.push = push;\n\t}\n\n\tpublic long getPullTimeDelayMillsWhenException() {\n\t\treturn pullTimeDelayMillsWhenException;\n\t}\n\n\tpublic RocketMQConsumerProperties setPullTimeDelayMillsWhenException(\n\t\t\tlong pullTimeDelayMillsWhenException) {\n\t\tthis.pullTimeDelayMillsWhenException = pullTimeDelayMillsWhenException;\n\t\treturn this;\n\t}\n\n\tpublic ConsumeFromWhere getConsumeFromWhere() {\n\t\treturn consumeFromWhere;\n\t}\n\n\tpublic RocketMQConsumerProperties setConsumeFromWhere(\n\t\t\tConsumeFromWhere consumeFromWhere) {\n\t\tthis.consumeFromWhere = consumeFromWhere;\n\t\treturn this;\n\t}\n\n\tpublic String getConsumeTimestamp() {\n\t\treturn consumeTimestamp;\n\t}\n\n\tpublic RocketMQConsumerProperties setConsumeTimestamp(String consumeTimestamp) {\n\t\tthis.consumeTimestamp = consumeTimestamp;\n\t\treturn this;\n\t}\n\n\tpublic int getPullThresholdForQueue() {\n\t\treturn pullThresholdForQueue;\n\t}\n\n\tpublic RocketMQConsumerProperties setPullThresholdForQueue(\n\t\t\tint pullThresholdForQueue) {\n\t\tthis.pullThresholdForQueue = pullThresholdForQueue;\n\t\treturn this;\n\t}\n\n\tpublic int getPullThresholdSizeForQueue() {\n\t\treturn pullThresholdSizeForQueue;\n\t}\n\n\tpublic RocketMQConsumerProperties setPullThresholdSizeForQueue(\n\t\t\tint pullThresholdSizeForQueue) {\n\t\tthis.pullThresholdSizeForQueue = pullThresholdSizeForQueue;\n\t\treturn this;\n\t}\n\n\tpublic int getPullBatchSize() {\n\t\treturn pullBatchSize;\n\t}\n\n\tpublic RocketMQConsumerProperties setPullBatchSize(int pullBatchSize) {\n\t\tthis.pullBatchSize = pullBatchSize;\n\t\treturn this;\n\t}\n\n\tpublic Pull getPull() {\n\t\treturn pull;\n\t}\n\n\tpublic RocketMQConsumerProperties setPull(Pull pull) {\n\t\tthis.pull = pull;\n\t\treturn this;\n\t}\n\n\tpublic int getConsumeMaxSpan() {\n\t\treturn consumeMaxSpan;\n\t}\n\n\tpublic RocketMQConsumerProperties setConsumeMaxSpan(int consumeMaxSpan) {\n\t\tthis.consumeMaxSpan = consumeMaxSpan;\n\t\treturn this;\n\t}\n\n\tpublic static class Push implements Serializable {\n\n\t\tprivate static final long serialVersionUID = -7398468554978817630L;\n\n\t\t/**\n\t\t * if orderly is true, using {@link MessageListenerOrderly} else if orderly if\n\t\t * false, using {@link MessageListenerConcurrently}.\n\t\t */\n\t\tprivate boolean orderly = false;\n\n\t\t/**\n\t\t * Suspending pulling time for cases requiring slow pulling like flow-control\n\t\t * scenario. see{@link ConsumeMessageOrderlyService#processConsumeResult}.\n\t\t * see{@link ConsumeOrderlyContext#getSuspendCurrentQueueTimeMillis}.\n\t\t */\n\t\tprivate int suspendCurrentQueueTimeMillis = 1000;\n\n\t\t/**\n\t\t * https://github.com/alibaba/spring-cloud-alibaba/issues/1866 Max re-consume\n\t\t * times. -1 means 16 times. If messages are re-consumed more than\n\t\t * {@link #maxReconsumeTimes} before success, it's be directed to a deletion queue\n\t\t * waiting.\n\t\t */\n\t\tprivate int maxReconsumeTimes;\n\n\t\t/**\n\t\t * for concurrently listener. message consume retry strategy. -1 means dlq(or\n\t\t * discard. see {@link ConsumeMessageConcurrentlyService#processConsumeResult}.\n\t\t * see {@link ConsumeConcurrentlyContext#getDelayLevelWhenNextConsume}.\n\t\t */\n\t\tprivate int delayLevelWhenNextConsume = 0;\n\n\t\t/**\n\t\t * Flow control threshold on topic level, default value is -1(Unlimited)\n\t\t * <p>\n\t\t * The value of {@code pullThresholdForQueue} will be overwrote and calculated\n\t\t * based on {@code pullThresholdForTopic} if it is't unlimited\n\t\t * <p>\n\t\t * For example, if the value of pullThresholdForTopic is 1000 and 10 message\n\t\t * queues are assigned to this consumer, then pullThresholdForQueue will be set to\n\t\t * 100.\n\t\t */\n\t\tprivate int pullThresholdForTopic = -1;\n\n\t\t/**\n\t\t * Limit the cached message size on topic level, default value is -1\n\t\t * MiB(Unlimited)\n\t\t * <p>\n\t\t * The value of {@code pullThresholdSizeForQueue} will be overwrote and calculated\n\t\t * based on {@code pullThresholdSizeForTopic} if it is't unlimited .\n\t\t * <p>\n\t\t * For example, if the value of pullThresholdSizeForTopic is 1000 MiB and 10\n\t\t * message queues are assigned to this consumer, then pullThresholdSizeForQueue\n\t\t * will be set to 100 MiB .\n\t\t */\n\t\tprivate int pullThresholdSizeForTopic = -1;\n\n\t\t/**\n\t\t * Message pull Interval.\n\t\t */\n\t\tprivate long pullInterval = 0;\n\n\t\t/**\n\t\t * Batch consumption size.\n\t\t */\n\t\tprivate int consumeMessageBatchMaxSize = 1;\n\n\t\t/**\n\t\t * Maximum amount of time in minutes a message may block the consuming thread.\n\t\t * Unit: Minutes\n\t\t */\n\t\tprivate long consumeTimeout = 15;\n\n\t\tpublic boolean getOrderly() {\n\t\t\treturn orderly;\n\t\t}\n\n\t\tpublic void setOrderly(boolean orderly) {\n\t\t\tthis.orderly = orderly;\n\t\t}\n\n\t\tpublic int getSuspendCurrentQueueTimeMillis() {\n\t\t\treturn suspendCurrentQueueTimeMillis;\n\t\t}\n\n\t\tpublic void setSuspendCurrentQueueTimeMillis(int suspendCurrentQueueTimeMillis) {\n\t\t\tthis.suspendCurrentQueueTimeMillis = suspendCurrentQueueTimeMillis;\n\t\t}\n\n\t\tpublic int getMaxReconsumeTimes() {\n\t\t\treturn maxReconsumeTimes;\n\t\t}\n\n\t\tpublic void setMaxReconsumeTimes(int maxReconsumeTimes) {\n\t\t\tthis.maxReconsumeTimes = maxReconsumeTimes;\n\t\t}\n\n\t\tpublic int getDelayLevelWhenNextConsume() {\n\t\t\treturn delayLevelWhenNextConsume;\n\t\t}\n\n\t\tpublic void setDelayLevelWhenNextConsume(int delayLevelWhenNextConsume) {\n\t\t\tthis.delayLevelWhenNextConsume = delayLevelWhenNextConsume;\n\t\t}\n\n\t\tpublic int getPullThresholdForTopic() {\n\t\t\treturn pullThresholdForTopic;\n\t\t}\n\n\t\tpublic void setPullThresholdForTopic(int pullThresholdForTopic) {\n\t\t\tthis.pullThresholdForTopic = pullThresholdForTopic;\n\t\t}\n\n\t\tpublic int getPullThresholdSizeForTopic() {\n\t\t\treturn pullThresholdSizeForTopic;\n\t\t}\n\n\t\tpublic void setPullThresholdSizeForTopic(int pullThresholdSizeForTopic) {\n\t\t\tthis.pullThresholdSizeForTopic = pullThresholdSizeForTopic;\n\t\t}\n\n\t\tpublic long getPullInterval() {\n\t\t\treturn pullInterval;\n\t\t}\n\n\t\tpublic void setPullInterval(long pullInterval) {\n\t\t\tthis.pullInterval = pullInterval;\n\t\t}\n\n\t\tpublic int getConsumeMessageBatchMaxSize() {\n\t\t\treturn consumeMessageBatchMaxSize;\n\t\t}\n\n\t\tpublic void setConsumeMessageBatchMaxSize(int consumeMessageBatchMaxSize) {\n\t\t\tthis.consumeMessageBatchMaxSize = consumeMessageBatchMaxSize;\n\t\t}\n\n\t\tpublic long getConsumeTimeout() {\n\t\t\treturn consumeTimeout;\n\t\t}\n\n\t\tpublic void setConsumeTimeout(long consumeTimeout) {\n\t\t\tthis.consumeTimeout = consumeTimeout;\n\t\t}\n\t}\n\n\tpublic static class Pull implements Serializable {\n\n\t\t/**\n\t\t * The poll timeout in milliseconds.\n\t\t */\n\t\tprivate long pollTimeoutMillis = 1000 * 5;\n\n\t\t/**\n\t\t * Pull thread number.\n\t\t */\n\t\tprivate int pullThreadNums = 20;\n\n\t\t/**\n\t\t * Interval time in in milliseconds for checking changes in topic metadata.\n\t\t */\n\t\tprivate long topicMetadataCheckIntervalMillis = 30 * 1000;\n\n\t\t/**\n\t\t * Long polling mode, the Consumer connection timeout(must greater than\n\t\t * brokerSuspendMaxTimeMillis), it is not recommended to modify.\n\t\t */\n\t\tprivate long consumerTimeoutMillisWhenSuspend = 1000 * 30;\n\n\t\t/**\n\t\t * Ack state handling, including receive, reject, and retry, when a consumption\n\t\t * exception occurs.\n\t\t */\n\t\tprivate String errAcknowledge;\n\n\t\tprivate long pullThresholdForAll = 1000L;\n\n\t\tpublic long getPollTimeoutMillis() {\n\t\t\treturn pollTimeoutMillis;\n\t\t}\n\n\t\tpublic void setPollTimeoutMillis(long pollTimeoutMillis) {\n\t\t\tthis.pollTimeoutMillis = pollTimeoutMillis;\n\t\t}\n\n\t\tpublic int getPullThreadNums() {\n\t\t\treturn pullThreadNums;\n\t\t}\n\n\t\tpublic void setPullThreadNums(int pullThreadNums) {\n\t\t\tthis.pullThreadNums = pullThreadNums;\n\t\t}\n\n\t\tpublic long getTopicMetadataCheckIntervalMillis() {\n\t\t\treturn topicMetadataCheckIntervalMillis;\n\t\t}\n\n\t\tpublic void setTopicMetadataCheckIntervalMillis(\n\t\t\t\tlong topicMetadataCheckIntervalMillis) {\n\t\t\tthis.topicMetadataCheckIntervalMillis = topicMetadataCheckIntervalMillis;\n\t\t}\n\n\t\tpublic long getConsumerTimeoutMillisWhenSuspend() {\n\t\t\treturn consumerTimeoutMillisWhenSuspend;\n\t\t}\n\n\t\tpublic void setConsumerTimeoutMillisWhenSuspend(\n\t\t\t\tlong consumerTimeoutMillisWhenSuspend) {\n\t\t\tthis.consumerTimeoutMillisWhenSuspend = consumerTimeoutMillisWhenSuspend;\n\t\t}\n\n\t\tpublic String getErrAcknowledge() {\n\t\t\treturn errAcknowledge;\n\t\t}\n\n\t\tpublic void setErrAcknowledge(String errAcknowledge) {\n\t\t\tthis.errAcknowledge = errAcknowledge;\n\t\t}\n\n\t\tpublic long getPullThresholdForAll() {\n\t\t\treturn pullThresholdForAll;\n\t\t}\n\n\t\tpublic void setPullThresholdForAll(long pullThresholdForAll) {\n\t\t\tthis.pullThresholdForAll = pullThresholdForAll;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQExtendedBindingProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.properties;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.cloud.stream.binder.AbstractExtendedBindingProperties;\nimport org.springframework.cloud.stream.binder.BinderSpecificPropertiesProvider;\n\n/**\n * rocketMQ specific extended binding properties class that extends from\n * {@link AbstractExtendedBindingProperties}.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\n@ConfigurationProperties(\"spring.cloud.stream.rocketmq\")\npublic class RocketMQExtendedBindingProperties extends\n\t\tAbstractExtendedBindingProperties<RocketMQConsumerProperties, RocketMQProducerProperties, RocketMQSpecificPropertiesProvider> {\n\n\tprivate static final String DEFAULTS_PREFIX = \"spring.cloud.stream.rocketmq.default\";\n\n\t@Override\n\tpublic String getDefaultsPrefix() {\n\t\treturn DEFAULTS_PREFIX;\n\t}\n\n\t@Override\n\tpublic Class<? extends BinderSpecificPropertiesProvider> getExtendedPropertiesEntryClass() {\n\t\treturn RocketMQSpecificPropertiesProvider.class;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.properties;\n\n/**\n * Extended producer properties for RocketMQ binder.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class RocketMQProducerProperties extends RocketMQCommonProperties {\n\n\t/**\n\t * Timeout for sending messages.\n\t */\n\tprivate int sendMsgTimeout = 3000;\n\n\t/**\n\t * Compress message body threshold, namely, message body larger than 4k will be\n\t * compressed on default.\n\t */\n\tprivate int compressMsgBodyThreshold = 1024 * 4;\n\n\t/**\n\t * Maximum number of retry to perform internally before claiming sending failure in\n\t * synchronous mode.\n\t *\n\t * This may potentially cause message duplication which is up to application\n\t * developers to resolve.\n\t */\n\tprivate int retryTimesWhenSendFailed = 2;\n\n\t/**\n\t * Maximum number of retry to perform internally before claiming sending failure in\n\t * asynchronous mode.\n\t *\n\t * This may potentially cause message duplication which is up to application\n\t * developers to resolve.\n\t */\n\tprivate int retryTimesWhenSendAsyncFailed = 2;\n\n\t/**\n\t * Indicate whether to retry another broker on sending failure internally.\n\t */\n\tprivate boolean retryAnotherBroker = false;\n\n\t/**\n\t * Maximum allowed message size in bytes.\n\t */\n\tprivate int maxMessageSize = 1024 * 1024 * 4;\n\n\tprivate String producerType = ProducerType.Normal.name();\n\n\tprivate String sendType = SendType.Sync.name();\n\n\tprivate String sendCallBack;\n\n\tprivate String transactionListener;\n\n\tprivate String messageQueueSelector;\n\n\tprivate String errorMessageStrategy;\n\n\tprivate String sendFailureChannel;\n\n\tprivate String checkForbiddenHook;\n\n\tprivate String sendMessageHook;\n\n\tpublic int getSendMsgTimeout() {\n\t\treturn sendMsgTimeout;\n\t}\n\n\tpublic void setSendMsgTimeout(int sendMsgTimeout) {\n\t\tthis.sendMsgTimeout = sendMsgTimeout;\n\t}\n\n\tpublic int getCompressMsgBodyThreshold() {\n\t\treturn compressMsgBodyThreshold;\n\t}\n\n\tpublic void setCompressMsgBodyThreshold(int compressMsgBodyThreshold) {\n\t\tthis.compressMsgBodyThreshold = compressMsgBodyThreshold;\n\t}\n\n\tpublic int getRetryTimesWhenSendFailed() {\n\t\treturn retryTimesWhenSendFailed;\n\t}\n\n\tpublic void setRetryTimesWhenSendFailed(int retryTimesWhenSendFailed) {\n\t\tthis.retryTimesWhenSendFailed = retryTimesWhenSendFailed;\n\t}\n\n\tpublic int getRetryTimesWhenSendAsyncFailed() {\n\t\treturn retryTimesWhenSendAsyncFailed;\n\t}\n\n\tpublic void setRetryTimesWhenSendAsyncFailed(int retryTimesWhenSendAsyncFailed) {\n\t\tthis.retryTimesWhenSendAsyncFailed = retryTimesWhenSendAsyncFailed;\n\t}\n\n\tpublic boolean getRetryAnotherBroker() {\n\t\treturn retryAnotherBroker;\n\t}\n\n\tpublic void setRetryAnotherBroker(boolean retryAnotherBroker) {\n\t\tthis.retryAnotherBroker = retryAnotherBroker;\n\t}\n\n\tpublic int getMaxMessageSize() {\n\t\treturn maxMessageSize;\n\t}\n\n\tpublic void setMaxMessageSize(int maxMessageSize) {\n\t\tthis.maxMessageSize = maxMessageSize;\n\t}\n\n\tpublic String getProducerType() {\n\t\treturn producerType;\n\t}\n\n\tpublic void setProducerType(String producerType) {\n\t\tthis.producerType = producerType;\n\t}\n\n\tpublic String getSendType() {\n\t\treturn sendType;\n\t}\n\n\tpublic void setSendType(String sendType) {\n\t\tthis.sendType = sendType;\n\t}\n\n\tpublic String getSendCallBack() {\n\t\treturn sendCallBack;\n\t}\n\n\tpublic void setSendCallBack(String sendCallBack) {\n\t\tthis.sendCallBack = sendCallBack;\n\t}\n\n\tpublic String getTransactionListener() {\n\t\treturn transactionListener;\n\t}\n\n\tpublic void setTransactionListener(String transactionListener) {\n\t\tthis.transactionListener = transactionListener;\n\t}\n\n\tpublic String getMessageQueueSelector() {\n\t\treturn messageQueueSelector;\n\t}\n\n\tpublic void setMessageQueueSelector(String messageQueueSelector) {\n\t\tthis.messageQueueSelector = messageQueueSelector;\n\t}\n\n\tpublic String getErrorMessageStrategy() {\n\t\treturn errorMessageStrategy;\n\t}\n\n\tpublic void setErrorMessageStrategy(String errorMessageStrategy) {\n\t\tthis.errorMessageStrategy = errorMessageStrategy;\n\t}\n\n\tpublic String getSendFailureChannel() {\n\t\treturn sendFailureChannel;\n\t}\n\n\tpublic void setSendFailureChannel(String sendFailureChannel) {\n\t\tthis.sendFailureChannel = sendFailureChannel;\n\t}\n\n\tpublic String getCheckForbiddenHook() {\n\t\treturn checkForbiddenHook;\n\t}\n\n\tpublic void setCheckForbiddenHook(String checkForbiddenHook) {\n\t\tthis.checkForbiddenHook = checkForbiddenHook;\n\t}\n\n\tpublic String getSendMessageHook() {\n\t\treturn sendMessageHook;\n\t}\n\n\tpublic void setSendMessageHook(String sendMessageHook) {\n\t\tthis.sendMessageHook = sendMessageHook;\n\t}\n\n\tpublic enum ProducerType {\n\n\t\t/**\n\t\t * Is not a transaction.\n\t\t */\n\t\tNormal,\n\t\t/**\n\t\t * a transaction.\n\t\t */\n\t\tTrans;\n\n\t\tpublic boolean equalsName(String name) {\n\t\t\treturn this.name().equalsIgnoreCase(name);\n\t\t}\n\n\t}\n\n\tpublic enum SendType {\n\n\t\t/**\n\t\t * one way.\n\t\t */\n\t\tOneWay,\n\t\t/**\n\t\t * Asynchronization Model.\n\t\t */\n\t\tAsync,\n\t\t/**\n\t\t * synchronization.\n\t\t */\n\t\tSync,;\n\n\t\tpublic boolean equalsName(String name) {\n\t\t\treturn this.name().equalsIgnoreCase(name);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQSpecificPropertiesProvider.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.properties;\n\nimport org.springframework.cloud.stream.binder.BinderSpecificPropertiesProvider;\n\n/**\n * Container object for RocketMQ specific extended producer and consumer binding\n * properties.\n *\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class RocketMQSpecificPropertiesProvider\n\t\timplements BinderSpecificPropertiesProvider {\n\n\t/**\n\t * Consumer specific binding properties. @see {@link RocketMQConsumerProperties}.\n\t */\n\tprivate RocketMQConsumerProperties consumer = new RocketMQConsumerProperties();\n\n\t/**\n\t * Producer specific binding properties. @see {@link RocketMQProducerProperties}.\n\t */\n\tprivate RocketMQProducerProperties producer = new RocketMQProducerProperties();\n\n\t/**\n\t * @return {@link RocketMQConsumerProperties} Consumer specific binding\n\t * properties. @see {@link RocketMQConsumerProperties}.\n\t */\n\t@Override\n\tpublic RocketMQConsumerProperties getConsumer() {\n\t\treturn this.consumer;\n\t}\n\n\tpublic void setConsumer(RocketMQConsumerProperties consumer) {\n\t\tthis.consumer = consumer;\n\t}\n\n\t/**\n\t * @return {@link RocketMQProducerProperties} Producer specific binding\n\t * properties. @see {@link RocketMQProducerProperties}.\n\t */\n\t@Override\n\tpublic RocketMQProducerProperties getProducer() {\n\t\treturn this.producer;\n\t}\n\n\tpublic void setProducer(RocketMQProducerProperties producer) {\n\t\tthis.producer = producer;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/provisioning/RocketMQTopicProvisioner.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.provisioning;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties;\nimport org.apache.rocketmq.client.Validators;\nimport org.apache.rocketmq.client.exception.MQClientException;\n\nimport org.springframework.cloud.stream.binder.ExtendedConsumerProperties;\nimport org.springframework.cloud.stream.binder.ExtendedProducerProperties;\nimport org.springframework.cloud.stream.provisioning.ConsumerDestination;\nimport org.springframework.cloud.stream.provisioning.ProducerDestination;\nimport org.springframework.cloud.stream.provisioning.ProvisioningException;\nimport org.springframework.cloud.stream.provisioning.ProvisioningProvider;\n\n/**\n * @author Timur Valiev\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class RocketMQTopicProvisioner implements\n\t\tProvisioningProvider<ExtendedConsumerProperties<RocketMQConsumerProperties>, ExtendedProducerProperties<RocketMQProducerProperties>> {\n\n\t@Override\n\tpublic ProducerDestination provisionProducerDestination(String name,\n\t\t\tExtendedProducerProperties<RocketMQProducerProperties> properties)\n\t\t\tthrows ProvisioningException {\n\t\tcheckTopic(name);\n\t\treturn new RocketProducerDestination(name);\n\t}\n\n\t@Override\n\tpublic ConsumerDestination provisionConsumerDestination(String name, String group,\n\t\t\tExtendedConsumerProperties<RocketMQConsumerProperties> properties)\n\t\t\tthrows ProvisioningException {\n\t\tcheckTopic(name);\n\t\treturn new RocketConsumerDestination(name);\n\t}\n\n\tprivate void checkTopic(String topic) {\n\t\ttry {\n\t\t\tValidators.checkTopic(topic);\n\t\t}\n\t\tcatch (MQClientException e) {\n\t\t\tthrow new AssertionError(e);\n\t\t}\n\t}\n\n\tprivate static final class RocketProducerDestination implements ProducerDestination {\n\n\t\tprivate final String producerDestinationName;\n\n\t\tRocketProducerDestination(String destinationName) {\n\t\t\tthis.producerDestinationName = destinationName;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getName() {\n\t\t\treturn producerDestinationName;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getNameForPartition(int partition) {\n\t\t\treturn producerDestinationName;\n\t\t}\n\n\t}\n\n\tprivate static final class RocketConsumerDestination implements ConsumerDestination {\n\n\t\tprivate final String consumerDestinationName;\n\n\t\tRocketConsumerDestination(String consumerDestinationName) {\n\t\t\tthis.consumerDestinationName = consumerDestinationName;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getName() {\n\t\t\treturn this.consumerDestinationName;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/provisioning/selector/PartitionMessageQueueSelector.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.provisioning.selector;\n\nimport java.util.List;\n\nimport org.apache.rocketmq.client.producer.MessageQueueSelector;\nimport org.apache.rocketmq.common.message.Message;\nimport org.apache.rocketmq.common.message.MessageQueue;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport org.springframework.cloud.stream.binder.BinderHeaders;\n\n/**\n * @author wangxing\n */\npublic class PartitionMessageQueueSelector implements MessageQueueSelector {\n\n\tprivate static final Logger LOGGER = LoggerFactory\n\t\t\t.getLogger(PartitionMessageQueueSelector.class);\n\n\t@Override\n\tpublic MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {\n\t\tint partition = 0;\n\t\ttry {\n\t\t\tpartition = Math.abs(\n\t\t\t\t\tInteger.parseInt(msg.getProperty(BinderHeaders.PARTITION_HEADER)));\n\t\t\tif (partition >= mqs.size()) {\n\t\t\t\tLOGGER.warn(\n\t\t\t\t\t\t\"the partition '{}' is greater than the number of queues '{}'.\",\n\t\t\t\t\t\tpartition, mqs.size());\n\t\t\t\tpartition = partition % mqs.size();\n\t\t\t}\n\t\t}\n\t\tcatch (NumberFormatException ignored) {\n\t\t}\n\t\treturn mqs.get(partition);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/AbstractRocketMQHeaderMapper.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.support;\n\nimport java.nio.charset.Charset;\nimport java.nio.charset.StandardCharsets;\n\nimport org.apache.rocketmq.common.message.MessageConst;\n\nimport org.springframework.messaging.MessageHeaders;\nimport org.springframework.util.Assert;\n\n/**\n * Base for RocketMQ header mappers.\n *\n * @author caotc\n * @since 2.1.1.RELEASE\n */\npublic abstract class AbstractRocketMQHeaderMapper implements RocketMQHeaderMapper {\n\n\tprivate static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;\n\n\tprivate Charset charset;\n\n\tpublic AbstractRocketMQHeaderMapper() {\n\t\tthis(DEFAULT_CHARSET);\n\t}\n\n\tpublic AbstractRocketMQHeaderMapper(Charset charset) {\n\t\tAssert.notNull(charset, \"'charset' cannot be null\");\n\t\tthis.charset = charset;\n\t}\n\n\tprotected boolean matches(String headerName) {\n\t\treturn !MessageConst.STRING_HASH_SET.contains(headerName)\n\t\t\t\t&& !MessageHeaders.ID.equals(headerName)\n\t\t\t\t&& !MessageHeaders.TIMESTAMP.equals(headerName)\n\t\t\t\t&& !MessageHeaders.CONTENT_TYPE.equals(headerName)\n\t\t\t\t&& !MessageHeaders.REPLY_CHANNEL.equals(headerName)\n\t\t\t\t&& !MessageHeaders.ERROR_CHANNEL.equals(headerName);\n\t}\n\n\tpublic Charset getCharset() {\n\t\treturn charset;\n\t}\n\n\tpublic void setCharset(Charset charset) {\n\t\tAssert.notNull(charset, \"'charset' cannot be null\");\n\t\tthis.charset = charset;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/JacksonRocketMQHeaderMapper.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.support;\n\nimport java.io.IOException;\nimport java.nio.charset.Charset;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport tools.jackson.core.type.TypeReference;\nimport tools.jackson.databind.ObjectMapper;\n\nimport org.springframework.messaging.MessageHeaders;\nimport org.springframework.util.ClassUtils;\n\n/**\n * jackson header mapper for RocketMQ. Header types are added to a special header\n * {@link #JSON_TYPES}.\n *\n * @author caotc\n * @since 2.1.1.RELEASE\n */\npublic class JacksonRocketMQHeaderMapper extends AbstractRocketMQHeaderMapper {\n\n\tprivate final static Logger log = LoggerFactory\n\t\t\t.getLogger(JacksonRocketMQHeaderMapper.class);\n\n\tprivate static final List<String> DEFAULT_TRUSTED_PACKAGES = Arrays\n\t\t\t.asList(\"java.lang\", \"java.net\", \"java.util\", \"org.springframework.util\");\n\n\t/**\n\t * Header name for java types of other headers.\n\t */\n\tpublic static final String JSON_TYPES = \"spring_json_header_types\";\n\n\tprivate final ObjectMapper objectMapper;\n\n\tprivate final Set<String> trustedPackages = new LinkedHashSet<>(\n\t\t\tDEFAULT_TRUSTED_PACKAGES);\n\n\tpublic JacksonRocketMQHeaderMapper(ObjectMapper objectMapper) {\n\t\tthis.objectMapper = objectMapper;\n\t}\n\n\tpublic JacksonRocketMQHeaderMapper(Charset charset, ObjectMapper objectMapper) {\n\t\tsuper(charset);\n\t\tthis.objectMapper = objectMapper;\n\t}\n\n\t@Override\n\tpublic Map<String, String> fromHeaders(MessageHeaders headers) {\n\t\tfinal Map<String, String> target = new HashMap<>();\n\t\tfinal Map<String, String> jsonHeaders = new HashMap<>();\n\t\theaders.forEach((key, value) -> {\n\t\t\tif (matches(key)) {\n\t\t\t\tif (value instanceof String strValue) {\n\t\t\t\t\ttarget.put(key, strValue);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tString className = value.getClass().getName();\n\t\t\t\t\t\ttarget.put(key, objectMapper.writeValueAsString(value));\n\t\t\t\t\t\tjsonHeaders.put(key, className);\n\t\t\t\t\t}\n\t\t\t\t\tcatch (Exception e) {\n\t\t\t\t\t\tlog.debug(\"Could not map \" + key + \" with type \"\n\t\t\t\t\t\t\t\t+ value.getClass().getName(), e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tif (jsonHeaders.size() > 0) {\n\t\t\ttry {\n\t\t\t\ttarget.put(JSON_TYPES, objectMapper.writeValueAsString(jsonHeaders));\n\t\t\t}\n\t\t\tcatch (IllegalStateException e) {\n\t\t\t\tlog.error(\"Could not add json types header\", e);\n\t\t\t}\n\t\t}\n\t\treturn target;\n\t}\n\n\t@Override\n\tpublic MessageHeaders toHeaders(Map<String, String> source) {\n\t\tfinal Map<String, Object> target = new HashMap<>();\n\t\tfinal Map<String, String> jsonTypes = decodeJsonTypes(source);\n\t\tsource.forEach((key, value) -> {\n\t\t\tif (matches(key) && !(key.equals(JSON_TYPES))) {\n\t\t\t\tif (jsonTypes.containsKey(key)) {\n\t\t\t\t\tClass<?> type = Object.class;\n\t\t\t\t\tString requestedType = jsonTypes.get(key);\n\t\t\t\t\tboolean trusted = trusted(requestedType);\n\t\t\t\t\tif (trusted) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\ttype = ClassUtils.forName(requestedType, null);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (Exception e) {\n\t\t\t\t\t\t\tlog.error(\"Could not load class for header: \" + key, e);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (trusted) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tObject val = decodeValue(value, type);\n\t\t\t\t\t\t\ttarget.put(key, val);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (IOException e) {\n\t\t\t\t\t\t\tlog.error(\"Could not decode json type: \" + value\n\t\t\t\t\t\t\t\t\t+ \" for key: \" + key, e);\n\t\t\t\t\t\t\ttarget.put(key, value);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\ttarget.put(key, new NonTrustedHeaderType(value, requestedType));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttarget.put(key, value);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn new MessageHeaders(target);\n\t}\n\n\t/**\n\t * @param packagesToTrust the packages to trust.\n\t * @see #addTrustedPackages(Collection)\n\t */\n\tpublic void addTrustedPackages(String... packagesToTrust) {\n\t\tif (Objects.nonNull(packagesToTrust)) {\n\t\t\taddTrustedPackages(Arrays.asList(packagesToTrust));\n\t\t}\n\t}\n\n\t/**\n\t * Add packages to the trusted packages list (default {@code java.util, java.lang})\n\t * used when constructing objects from JSON. If any of the supplied packages is\n\t * {@code \"*\"}, all packages are trusted. If a class for a non-trusted package is\n\t * encountered, the header is returned to the application with value of type\n\t * {@link NonTrustedHeaderType}.\n\t * @param packagesToTrust the packages to trust.\n\t */\n\tpublic void addTrustedPackages(Collection<String> packagesToTrust) {\n\t\tif (packagesToTrust != null) {\n\t\t\tfor (String whiteList : packagesToTrust) {\n\t\t\t\tif (\"*\".equals(whiteList)) {\n\t\t\t\t\tthis.trustedPackages.clear();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.trustedPackages.add(whiteList);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic Set<String> getTrustedPackages() {\n\t\treturn this.trustedPackages;\n\t}\n\n\tpublic ObjectMapper getObjectMapper() {\n\t\treturn objectMapper;\n\t}\n\n\tprivate Object decodeValue(String jsonString, Class<?> type)\n\t\t\tthrows IOException, LinkageError {\n\t\tObject value = objectMapper.readValue(jsonString, type);\n\t\tif (type.equals(NonTrustedHeaderType.class)) {\n\t\t\t// Upstream NTHT propagated; may be trusted here...\n\t\t\tNonTrustedHeaderType nth = (NonTrustedHeaderType) value;\n\t\t\tif (trusted(nth.getUntrustedType())) {\n\t\t\t\ttry {\n\t\t\t\t\tvalue = objectMapper.readValue(nth.getHeaderValue(),\n\t\t\t\t\t\t\tClassUtils.forName(nth.getUntrustedType(), null));\n\t\t\t\t}\n\t\t\t\tcatch (Exception e) {\n\t\t\t\t\tlog.error(\"Could not decode header: \" + nth, e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn value;\n\t}\n\n\tprivate Map<String, String> decodeJsonTypes(Map<String, String> source) {\n\t\tif (source.containsKey(JSON_TYPES)) {\n\t\t\tString value = source.get(JSON_TYPES);\n\t\t\ttry {\n\t\t\t\treturn objectMapper.readValue(value,\n\t\t\t\t\t\tnew TypeReference<Map<String, String>>() {\n\t\t\t\t\t\t});\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\t\t\t\tlog.error(\"Could not decode json types: \" + value, e);\n\t\t\t}\n\t\t}\n\t\treturn Collections.emptyMap();\n\t}\n\n\tprotected boolean trusted(String requestedType) {\n\t\tif (requestedType.equals(NonTrustedHeaderType.class.getName())) {\n\t\t\treturn true;\n\t\t}\n\t\tif (!this.trustedPackages.isEmpty()) {\n\t\t\tint lastDot = requestedType.lastIndexOf('.');\n\t\t\tif (lastDot < 0) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tString packageName = requestedType.substring(0, lastDot);\n\t\t\tfor (String trustedPackage : this.trustedPackages) {\n\t\t\t\tif (packageName.equals(trustedPackage)\n\t\t\t\t\t\t|| packageName.startsWith(trustedPackage + \".\")) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Represents a header that could not be decoded due to an untrusted type.\n\t */\n\tpublic static class NonTrustedHeaderType {\n\n\t\tprivate String headerValue;\n\n\t\tprivate String untrustedType;\n\n\t\tpublic NonTrustedHeaderType() {\n\t\t\tsuper();\n\t\t}\n\n\t\tNonTrustedHeaderType(String headerValue, String untrustedType) {\n\t\t\tthis.headerValue = headerValue;\n\t\t\tthis.untrustedType = untrustedType;\n\t\t}\n\n\t\tpublic void setHeaderValue(String headerValue) {\n\t\t\tthis.headerValue = headerValue;\n\t\t}\n\n\t\tpublic String getHeaderValue() {\n\t\t\treturn this.headerValue;\n\t\t}\n\n\t\tpublic void setUntrustedType(String untrustedType) {\n\t\t\tthis.untrustedType = untrustedType;\n\t\t}\n\n\t\tpublic String getUntrustedType() {\n\t\t\treturn this.untrustedType;\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn \"NonTrustedHeaderType [headerValue=\" + headerValue + \", untrustedType=\"\n\t\t\t\t\t+ this.untrustedType + \"]\";\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQHeaderMapper.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.support;\n\nimport java.util.Map;\n\nimport org.springframework.messaging.MessageHeaders;\n\n/**\n * header value mapper for RocketMQ.\n *\n * @author caotc\n * @since 2.1.1.RELEASE\n */\npublic interface RocketMQHeaderMapper {\n\n\t/**\n\t * Map from the given {@link MessageHeaders} to the specified target message.\n\t * @param headers the abstracted MessageHeaders.\n\t * @return the native target message.\n\t */\n\tMap<String, String> fromHeaders(MessageHeaders headers);\n\n\t/**\n\t * Map from the given target message to abstracted {@link MessageHeaders}.\n\t * @param source the native target message.\n\t * @return the target headers.\n\t */\n\tMessageHeaders toHeaders(Map<String, String> source);\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.support;\n\nimport java.nio.charset.Charset;\nimport java.util.Map;\nimport java.util.Objects;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.constant.RocketMQConst;\nimport com.alibaba.cloud.stream.binder.rocketmq.constant.RocketMQConst.Headers;\nimport com.alibaba.cloud.stream.binder.rocketmq.convert.RocketMQMessageConverter;\nimport com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQBeanContainerCache;\nimport org.apache.rocketmq.common.message.MessageConst;\nimport org.apache.rocketmq.common.message.MessageExt;\n\nimport org.springframework.messaging.Message;\nimport org.springframework.messaging.MessageHeaders;\nimport org.springframework.messaging.converter.CompositeMessageConverter;\nimport org.springframework.messaging.support.MessageBuilder;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.util.MimeTypeUtils;\nimport org.springframework.util.ObjectUtils;\n\n/**\n * @author zkzlx\n */\npublic final class RocketMQMessageConverterSupport {\n\n\tprivate RocketMQMessageConverterSupport() {\n\t}\n\n\tprivate static final CompositeMessageConverter MESSAGE_CONVERTER = RocketMQBeanContainerCache\n\t\t\t.getBean(RocketMQMessageConverter.DEFAULT_NAME,\n\t\t\t\t\tCompositeMessageConverter.class,\n\t\t\t\t\tnew RocketMQMessageConverter().getMessageConverter());\n\n\tpublic static Message convertMessage2Spring(MessageExt message) {\n\t\tMessageBuilder messageBuilder = MessageBuilder.withPayload(message.getBody())\n\t\t\t\t.setHeader(toRocketHeaderKey(Headers.KEYS), message.getKeys())\n\t\t\t\t.setHeader(toRocketHeaderKey(Headers.TAGS), message.getTags())\n\t\t\t\t.setHeader(toRocketHeaderKey(Headers.TOPIC), message.getTopic())\n\t\t\t\t.setHeader(toRocketHeaderKey(Headers.MESSAGE_ID), message.getMsgId())\n\t\t\t\t.setHeader(toRocketHeaderKey(Headers.BORN_TIMESTAMP),\n\t\t\t\t\t\tmessage.getBornTimestamp())\n\t\t\t\t.setHeader(toRocketHeaderKey(Headers.BORN_HOST),\n\t\t\t\t\t\tmessage.getBornHostString())\n\t\t\t\t.setHeader(toRocketHeaderKey(Headers.FLAG), message.getFlag())\n\t\t\t\t.setHeader(toRocketHeaderKey(Headers.QUEUE_ID), message.getQueueId())\n\t\t\t\t.setHeader(toRocketHeaderKey(Headers.SYS_FLAG), message.getSysFlag())\n\t\t\t\t.setHeader(toRocketHeaderKey(Headers.TRANSACTION_ID),\n\t\t\t\t\t\tmessage.getTransactionId());\n\t\taddUserProperties(message.getProperties(), messageBuilder);\n\t\treturn messageBuilder.build();\n\t}\n\n\tpublic static String toRocketHeaderKey(String rawKey) {\n\t\treturn \"ROCKET_\" + rawKey;\n\t}\n\n\tprivate static void addUserProperties(Map<String, String> properties,\n\t\t\tMessageBuilder messageBuilder) {\n\t\tif (!CollectionUtils.isEmpty(properties)) {\n\t\t\tproperties.forEach((key, val) -> {\n\t\t\t\tif (!MessageConst.STRING_HASH_SET.contains(key)\n\t\t\t\t\t\t&& !MessageHeaders.ID.equals(key)\n\t\t\t\t\t\t&& !MessageHeaders.TIMESTAMP.equals(key)) {\n\t\t\t\t\tmessageBuilder.setHeader(key, val);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic static org.apache.rocketmq.common.message.Message convertMessage2MQ(\n\t\t\tString destination, Message<?> source) {\n\t\tMessage<?> message = MESSAGE_CONVERTER.toMessage(source.getPayload(),\n\t\t\t\tsource.getHeaders());\n\t\tassert message != null;\n\t\tMessageBuilder<?> builder = MessageBuilder.fromMessage(message);\n\t\tbuilder.setHeaderIfAbsent(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN);\n\t\tmessage = builder.build();\n\t\treturn doConvert(destination, message);\n\t}\n\n\tprivate static org.apache.rocketmq.common.message.Message doConvert(String topic,\n\t\t\tMessage<?> message) {\n\t\tCharset charset = Charset.defaultCharset();\n\t\tObject payloadObj = message.getPayload();\n\t\tbyte[] payloads;\n\t\ttry {\n\t\t\tif (payloadObj instanceof String payload) {\n\t\t\t\tpayloads = payload.getBytes(charset);\n\t\t\t}\n\t\t\telse if (payloadObj instanceof byte[] payload) {\n\t\t\t\tpayloads = payload;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tString jsonObj = (String) MESSAGE_CONVERTER.fromMessage(message,\n\t\t\t\t\t\tpayloadObj.getClass());\n\t\t\t\tif (null == jsonObj) {\n\t\t\t\t\tthrow new RuntimeException(String.format(\n\t\t\t\t\t\t\t\"empty after conversion [messageConverter:%s,payloadClass:%s,payloadObj:%s]\",\n\t\t\t\t\t\t\tMESSAGE_CONVERTER.getClass(), payloadObj.getClass(),\n\t\t\t\t\t\t\tpayloadObj));\n\t\t\t\t}\n\t\t\t\tpayloads = jsonObj.getBytes(charset);\n\t\t\t}\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new RuntimeException(\"convert to RocketMQ message failed.\", e);\n\t\t}\n\t\treturn getAndWrapMessage(topic, message.getHeaders(), payloads);\n\t}\n\n\tprivate static org.apache.rocketmq.common.message.Message getAndWrapMessage(\n\t\t\tString topic, MessageHeaders headers, byte[] payloads) {\n\t\tif (topic == null || topic.length() < 1) {\n\t\t\treturn null;\n\t\t}\n\t\tif (payloads == null || payloads.length < 1) {\n\t\t\treturn null;\n\t\t}\n\t\torg.apache.rocketmq.common.message.Message rocketMsg = new org.apache.rocketmq.common.message.Message(\n\t\t\t\ttopic, payloads);\n\t\tif (Objects.nonNull(headers) && !headers.isEmpty()) {\n\t\t\tObject tag = headers.getOrDefault(Headers.TAGS,\n\t\t\t\t\theaders.get(toRocketHeaderKey(Headers.TAGS)));\n\t\t\tif (!ObjectUtils.isEmpty(tag)) {\n\t\t\t\trocketMsg.setTags(String.valueOf(tag));\n\t\t\t}\n\n\t\t\tObject keys = headers.getOrDefault(Headers.KEYS,\n\t\t\t\t\theaders.get(toRocketHeaderKey(Headers.KEYS)));\n\t\t\tif (!ObjectUtils.isEmpty(keys)) {\n\t\t\t\trocketMsg.setKeys(keys.toString());\n\t\t\t}\n\t\t\tObject flagObj = headers.getOrDefault(Headers.FLAG,\n\t\t\t\t\theaders.get(toRocketHeaderKey(Headers.FLAG)));\n\t\t\tint flag = 0;\n\t\t\tint delayLevel = 0;\n\t\t\ttry {\n\t\t\t\tflagObj = flagObj == null ? 0 : flagObj;\n\t\t\t\tObject delayLevelObj = headers.getOrDefault(\n\t\t\t\t\t\tRocketMQConst.PROPERTY_DELAY_TIME_LEVEL,\n\t\t\t\t\t\theaders.get(toRocketHeaderKey(\n\t\t\t\t\t\t\t\tRocketMQConst.PROPERTY_DELAY_TIME_LEVEL)));\n\t\t\t\tdelayLevelObj = delayLevelObj == null ? 0 : delayLevelObj;\n\t\t\t\tdelayLevel = Integer.parseInt(String.valueOf(delayLevelObj));\n\t\t\t\tflag = Integer.parseInt(String.valueOf(flagObj));\n\t\t\t}\n\t\t\tcatch (Exception ignored) {\n\t\t\t}\n\t\t\tif (delayLevel > 0) {\n\t\t\t\trocketMsg.setDelayTimeLevel(delayLevel);\n\t\t\t}\n\t\t\trocketMsg.setFlag(flag);\n\t\t\tObject waitStoreMsgOkObj = headers\n\t\t\t\t\t.getOrDefault(RocketMQConst.PROPERTY_WAIT_STORE_MSG_OK, \"true\");\n\t\t\trocketMsg.setWaitStoreMsgOK(\n\t\t\t\t\tBoolean.parseBoolean(String.valueOf(waitStoreMsgOkObj)));\n\t\t\theaders.entrySet().stream()\n\t\t\t\t\t.filter(entry -> !Objects.equals(entry.getKey(), Headers.FLAG))\n\t\t\t\t\t.forEach(entry -> {\n\t\t\t\t\t\tif (!MessageConst.STRING_HASH_SET.contains(entry.getKey())) {\n\t\t\t\t\t\t\tString val = String.valueOf(entry.getValue());\n\t\t\t\t\t\t\t// Remove All blank header(rocketmq not support).\n\t\t\t\t\t\t\tif (org.apache.commons.lang3.StringUtils.isNotBlank(val)) {\n\t\t\t\t\t\t\t\trocketMsg.putUserProperty(entry.getKey(), val);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t}\n\t\treturn rocketMsg;\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.utils;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.constant.RocketMQConst;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQCommonProperties;\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.rocketmq.acl.common.AclClientRPCHook;\nimport org.apache.rocketmq.acl.common.SessionCredentials;\nimport org.apache.rocketmq.client.consumer.MessageSelector;\nimport org.apache.rocketmq.common.UtilAll;\nimport org.apache.rocketmq.remoting.RPCHook;\n\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic final class RocketMQUtils {\n\n\tprivate RocketMQUtils() {\n\t}\n\n\tpublic static <T extends RocketMQCommonProperties> T mergeRocketMQProperties(\n\t\t\tRocketMQBinderConfigurationProperties binderConfigurationProperties,\n\t\t\tT mqProperties) {\n\t\tif (null == binderConfigurationProperties || mqProperties == null) {\n\t\t\treturn mqProperties;\n\t\t}\n\t\tif (StringUtils.isEmpty(mqProperties.getNameServer())) {\n\t\t\tmqProperties.setNameServer(binderConfigurationProperties.getNameServer());\n\t\t}\n\t\tif (StringUtils.isEmpty(mqProperties.getSecretKey())) {\n\t\t\tmqProperties.setSecretKey(binderConfigurationProperties.getSecretKey());\n\t\t}\n\t\tif (StringUtils.isEmpty(mqProperties.getAccessKey())) {\n\t\t\tmqProperties.setAccessKey(binderConfigurationProperties.getAccessKey());\n\t\t}\n\t\tif (StringUtils.isEmpty(mqProperties.getAccessChannel())) {\n\t\t\tmqProperties\n\t\t\t\t\t.setAccessChannel(binderConfigurationProperties.getAccessChannel());\n\t\t}\n\t\tif (StringUtils.isEmpty(mqProperties.getNamespace())) {\n\t\t\tmqProperties.setNamespace(binderConfigurationProperties.getNamespace());\n\t\t}\n\t\tif (StringUtils.isEmpty(mqProperties.getNamespaceV2())) {\n\t\t\tmqProperties.setNamespaceV2(binderConfigurationProperties.getNamespaceV2());\n\t\t}\n\t\tif (StringUtils.isEmpty(mqProperties.getGroup())) {\n\t\t\tmqProperties.setGroup(binderConfigurationProperties.getGroup());\n\t\t}\n\t\tif (StringUtils.isEmpty(mqProperties.getCustomizedTraceTopic())) {\n\t\t\tmqProperties.setCustomizedTraceTopic(\n\t\t\t\t\tbinderConfigurationProperties.getCustomizedTraceTopic());\n\t\t}\n\t\tif (StringUtils.isEmpty(mqProperties.getUnitName())) {\n\t\t\tmqProperties.setUnitName(binderConfigurationProperties.getUnitName());\n\t\t}\n\t\tmqProperties.setNameServer(getNameServerStr(mqProperties.getNameServer()));\n\t\treturn mqProperties;\n\t}\n\n\tpublic static String getInstanceName(RPCHook rpcHook, String identify) {\n\t\tString separator = \"|\";\n\t\tStringBuilder instanceName = new StringBuilder();\n\t\tif (null != rpcHook) {\n\t\t\tSessionCredentials sessionCredentials = ((AclClientRPCHook) rpcHook)\n\t\t\t\t\t.getSessionCredentials();\n\t\t\tinstanceName.append(sessionCredentials.getAccessKey()).append(separator);\n\t\t}\n\t\tinstanceName.append(identify).append(separator).append(UtilAll.getPid())\n\t\t\t\t.append(separator).append(Long.toString(System.nanoTime(), 36));\n\t\treturn instanceName.toString();\n\t}\n\n\tpublic static String getNameServerStr(String nameServer) {\n\t\tif (StringUtils.isEmpty(nameServer)) {\n\t\t\treturn RocketMQConst.DEFAULT_NAME_SERVER;\n\t\t}\n\t\treturn nameServer.replaceAll(\",\", \";\");\n\t}\n\n\tprivate static final String SQL = \"sql:\";\n\n\tpublic static MessageSelector getMessageSelector(String expression) {\n\t\tif (StringUtils.isNotBlank(expression) && expression.startsWith(SQL)) {\n\t\t\treturn MessageSelector.bySql(expression.replaceFirst(SQL, \"\"));\n\t\t}\n\t\treturn MessageSelector.byTag(expression);\n\t}\n\n\t/**\n\t * generate anonymous group.\n\t * @param destination not null\n\t * @return anonymous group name.\n\t */\n\tpublic static String anonymousGroup(final String destination) {\n\t\treturn RocketMQConst.DEFAULT_GROUP + \"_\" + destination;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/native-image/com.alibaba.cloud/spring-cloud-starter-stream-rocketmq/native-image.properties",
    "content": "Args = --initialize-at-build-time=org.apache.commons.logging.LogFactoryService \\\n\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/native-image/reflect-config.json",
    "content": "[\n  {\n    \"name\": \"org.apache.rocketmq.client.consumer.store.OffsetSerializeWrapper\",\n    \"allDeclaredFields\": true,\n    \"queryAllPublicMethods\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.consumer.ConsumeFromWhere\",\n    \"allPublicFields\": true,\n    \"queryAllPublicMethods\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.message.MessageQueue\",\n    \"allDeclaredFields\": true,\n    \"queryAllPublicMethods\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.header.GetMaxOffsetRequestHeader\",\n    \"allDeclaredFields\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.header.GetMaxOffsetResponseHeader\",\n    \"allDeclaredFields\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.header.NotifyConsumerIdsChangedRequestHeader\",\n    \"allDeclaredFields\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.header.PullMessageRequestHeader\",\n    \"allDeclaredFields\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.header.PullMessageResponseHeader\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.header.SendMessageRequestHeaderV2\",\n    \"allDeclaredFields\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.header.SendMessageResponseHeader\",\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.header.UnregisterClientRequestHeader\",\n    \"allDeclaredFields\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.header.namesrv.GetRouteInfoRequestHeader\",\n    \"allDeclaredFields\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.heartbeat.ConsumeType\",\n    \"allPublicFields\": true,\n    \"queryAllPublicMethods\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.heartbeat.ConsumerData\",\n    \"allDeclaredFields\": true,\n    \"allPublicMethods\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.heartbeat.HeartbeatData\",\n    \"allDeclaredFields\": true,\n    \"allPublicMethods\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.heartbeat.MessageModel\",\n    \"allPublicFields\": true,\n    \"queryAllPublicMethods\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.heartbeat.ProducerData\",\n    \"allDeclaredFields\": true,\n    \"allPublicMethods\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.heartbeat.SubscriptionData\",\n    \"allDeclaredFields\": true,\n    \"allPublicMethods\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.route.BrokerData\",\n    \"allDeclaredFields\": true,\n    \"allPublicMethods\": true,\n    \"allPublicConstructors\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.route.QueueData\",\n    \"allDeclaredFields\": true,\n    \"allPublicMethods\": true,\n    \"allPublicConstructors\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.route.TopicRouteData\",\n    \"allDeclaredFields\": true,\n    \"allPublicMethods\": true,\n    \"allPublicConstructors\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.remoting.netty.NettyDecoder\"\n  },\n  {\n    \"name\": \"org.apache.rocketmq.remoting.netty.NettyEncoder\"\n  },\n  {\n    \"name\": \"org.apache.rocketmq.remoting.netty.NettyRemotingClient$4\"\n  },\n  {\n    \"name\": \"org.apache.rocketmq.remoting.netty.NettyRemotingClient$NettyClientHandler\"\n  },\n  {\n    \"name\": \"org.apache.rocketmq.remoting.netty.NettyRemotingClient$NettyConnectManageHandler\",\n    \"methods\": [\n      {\n        \"name\": \"close\",\n        \"parameterTypes\": [\n          \"io.netty.channel.ChannelHandlerContext\",\n          \"io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"connect\",\n        \"parameterTypes\": [\n          \"io.netty.channel.ChannelHandlerContext\",\n          \"java.net.SocketAddress\",\n          \"java.net.SocketAddress\",\n          \"io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"disconnect\",\n        \"parameterTypes\": [\n          \"io.netty.channel.ChannelHandlerContext\",\n          \"io.netty.channel.ChannelPromise\"\n        ]\n      },\n      {\n        \"name\": \"exceptionCaught\",\n        \"parameterTypes\": [\n          \"io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Throwable\"\n        ]\n      },\n      {\n        \"name\": \"userEventTriggered\",\n        \"parameterTypes\": [\n          \"io.netty.channel.ChannelHandlerContext\",\n          \"java.lang.Object\"\n        ]\n      }\n    ]\n  },\n  {\n    \"name\": \"org.apache.rocketmq.remoting.protocol.LanguageCode\",\n    \"allPublicFields\": true,\n    \"queryAllPublicMethods\": true,\n    \"queryAllDeclaredConstructors\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.remoting.protocol.RemotingCommand\",\n    \"allDeclaredFields\": true,\n    \"allDeclaredMethods\": true,\n    \"allDeclaredConstructors\": true,\n    \"queryAllPublicMethods\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.remoting.protocol.RemotingSerializable\",\n    \"allDeclaredFields\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.remoting.protocol.SerializeType\",\n    \"allPublicFields\": true,\n    \"queryAllPublicMethods\": true,\n    \"queryAllDeclaredConstructors\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.header.GetConsumerListByGroupResponseBody\",\n    \"allDeclaredFields\": true,\n    \"allPublicFields\": true,\n    \"allPublicMethods\": true,\n    \"allDeclaredConstructors\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.header.GetConsumerListByGroupRequestHeader\",\n    \"allDeclaredFields\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.body.CheckClientRequestBody\",\n    \"allDeclaredFields\": true,\n    \"allPublicMethods\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.header.QueryConsumerOffsetRequestHeader\",\n    \"allDeclaredFields\": true\n  },\n  {\n    \"name\": \"org.apache.rocketmq.common.protocol.header.QueryConsumerOffsetResponseHeader\",\n    \"allDeclaredFields\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": []\n      }\n    ]\n  },\n  {\n    \"name\": \"org.apache.rocketmq.client.consumer.store.OffsetSerializeWrapper\",\n    \"allPublicMethods\": true\n  },\n  {\n    \"name\": \"com.alibaba.fastjson.support.spring.messaging.MappingFastJsonMessageConverter\",\n    \"allDeclaredConstructors\": true,\n    \"allDeclaredFields\": true,\n    \"allDeclaredMethods\": true\n  },\n  {\n    \"name\": \"org.springframework.integration.config.ConverterRegistrar$IntegrationConverterRegistration\",\n    \"allDeclaredFields\": true,\n    \"queryAllDeclaredMethods\": true,\n    \"queryAllDeclaredConstructors\": true,\n    \"methods\": [\n      {\n        \"name\": \"<init>\",\n        \"parameterTypes\": [\n          \"java.lang.Object\"\n        ]\n      },\n      {\n        \"name\": \"converter\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"equals\",\n        \"parameterTypes\": [\n          \"java.lang.Object\"\n        ]\n      },\n      {\n        \"name\": \"hashCode\",\n        \"parameterTypes\": []\n      },\n      {\n        \"name\": \"toString\",\n        \"parameterTypes\": []\n      }\n    ]\n  }\n]\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring/aot.factories",
    "content": "org.springframework.aot.hint.RuntimeHintsRegistrar=\\\ncom.alibaba.cloud.stream.binder.rocketmq.aot.hint.RocketMQSpecificPropertiesProviderHints,\\\ncom.alibaba.cloud.stream.binder.rocketmq.aot.hint.RocketMQConsumerPropertiesHints\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports",
    "content": "com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate.ExtendedBindingHandlerMappingsProviderConfiguration\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.binders",
    "content": "rocketmq:com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate.RocketMQBinderAutoConfiguration"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate.RocketMQBinderAutoConfiguration;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQExtendedBindingProperties;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.boot.autoconfigure.AutoConfigurations;\nimport org.springframework.boot.test.context.runner.ApplicationContextRunner;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author <a href=\"mailto:fangjian0423@gmail.com\">Jim</a>\n */\npublic class RocketMQAutoConfigurationTests {\n\n\tprivate ApplicationContextRunner contextRunner = new ApplicationContextRunner()\n\t\t\t.withConfiguration(\n\t\t\t\t\tAutoConfigurations.of(RocketMQBinderAutoConfiguration.class))\n\t\t\t.withPropertyValues(\n\t\t\t\t\t\"spring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876,127.0.0.1:9877\",\n\t\t\t\t\t\"spring.cloud.stream.bindings.output.destination=TopicOrderTest\",\n\t\t\t\t\t\"spring.cloud.stream.bindings.output.content-type=application/json\",\n\n\t\t\t\t\t\"spring.cloud.stream.bindings.input1.destination=TopicOrderTest\",\n\t\t\t\t\t\"spring.cloud.stream.bindings.input1.content-type=application/json\",\n\t\t\t\t\t\"spring.cloud.stream.bindings.input1.group=test-group1\",\n\t\t\t\t\t\"spring.cloud.stream.rocketmq.bindings.input1.consumer.push.orderly=true\",\n\t\t\t\t\t\"spring.cloud.stream.bindings.input1.consumer.maxAttempts=1\",\n\t\t\t\t\t\"spring.cloud.stream.bindings.input2.destination=TopicOrderTest\",\n\t\t\t\t\t\"spring.cloud.stream.bindings.input2.content-type=application/json\",\n\t\t\t\t\t\"spring.cloud.stream.bindings.input2.group=test-group2\",\n\t\t\t\t\t\"spring.cloud.stream.rocketmq.bindings.input2.consumer.push.orderly=false\",\n\t\t\t\t\t\"spring.cloud.stream.rocketmq.bindings.input2.consumer.subscription=tag1\");\n\n\t@Test\n\tpublic void testProperties() {\n\t\tthis.contextRunner.run(context -> {\n\t\t\tRocketMQBinderConfigurationProperties binderConfigurationProperties = context\n\t\t\t\t\t.getBean(RocketMQBinderConfigurationProperties.class);\n\t\t\tassertThat(binderConfigurationProperties.getNameServer())\n\t\t\t\t\t.isEqualTo(\"127.0.0.1:9876,127.0.0.1:9877\");\n\t\t\tRocketMQExtendedBindingProperties bindingProperties = context\n\t\t\t\t\t.getBean(RocketMQExtendedBindingProperties.class);\n\t\t\tassertThat(bindingProperties.getExtendedConsumerProperties(\"input2\")\n\t\t\t\t\t.getSubscription()).isEqualTo(\"tag1\");\n\t\t\tassertThat(bindingProperties.getExtendedConsumerProperties(\"input2\").getPush()\n\t\t\t\t\t.getOrderly()).isFalse();\n\t\t\tassertThat(bindingProperties.getExtendedConsumerProperties(\"input1\").getPush()\n\t\t\t\t\t.getOrderly()).isTrue();\n\t\t});\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinderTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq;\n\n\nimport com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate.ExtendedBindingHandlerMappingsProviderConfiguration;\nimport com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate.RocketMQBinderAutoConfiguration;\nimport com.alibaba.cloud.stream.binder.rocketmq.constant.RocketMQConst;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;\nimport jakarta.annotation.Resource;\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.cloud.stream.binder.ExtendedConsumerProperties;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.integration.core.MessageProducer;\n\nimport static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE;\n\n@SpringBootTest(classes = RocketMQMessageChannelBinderTest.TestConfig.class,\n\twebEnvironment = NONE,\n\tproperties = {\n\t\t\t\"spring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876\",\n\t\t\t\"spring.cloud.stream.bindings.output.destination=TopicOrderTest\",\n\t\t\t\"spring.cloud.stream.bindings.output.content-type=application/json\",\n\n\t\t\t\"spring.cloud.stream.bindings.input1.destination=TopicOrderTest\",\n\t\t\t\"spring.cloud.stream.bindings.input1.content-type=application/json\",\n\t\t\t\"spring.cloud.stream.bindings.input1.group=test-group1\",\n\t\t\t\"spring.cloud.stream.rocketmq.bindings.input1.consumer.push.orderly=true\",\n\t\t\t\"spring.cloud.stream.bindings.input1.consumer.maxAttempts=1\",\n\t\t\t\"spring.cloud.stream.bindings.input2.destination=TopicOrderTest\",\n\t\t\t\"spring.cloud.stream.bindings.input2.content-type=application/json\",\n\t\t\t\"spring.cloud.stream.bindings.input2.group=test-group2\",\n\t\t\t\"spring.cloud.stream.rocketmq.bindings.input2.consumer.push.orderly=false\",\n\t\t\t\"spring.cloud.stream.rocketmq.bindings.input2.consumer.subscription=tag1\"\n\t})\npublic class RocketMQMessageChannelBinderTest {\n\t@Resource\n\tRocketMQMessageChannelBinder binder;\n\n\t@Test\n\tpublic void createConsumerEndpoint() throws Exception {\n\t\tTestConsumerDestination destination = new TestConsumerDestination(\"test\");\n\t\tMessageProducer consumerEndpoint = binder.createConsumerEndpoint(destination, \"test\",\n\t\t\t\tnew ExtendedConsumerProperties<>(new RocketMQConsumerProperties()));\n\t\tAssertions.assertThat(consumerEndpoint).isNotNull();\n\t}\n\n\t@Test\n\tpublic void createAnymousConsumerEndpoint() throws Exception {\n\t\tExtendedConsumerProperties<RocketMQConsumerProperties> extendedConsumerProperties\n\t\t\t\t= new ExtendedConsumerProperties<>(new RocketMQConsumerProperties());\n\n\t\textendedConsumerProperties.populateBindingName(\"input1\");\n\t\tTestConsumerDestination destination = new TestConsumerDestination(\"test\");\n\t\tMessageProducer consumerEndpoint = binder.createConsumerEndpoint(destination, null,\n\t\t\t\textendedConsumerProperties);\n\t\tAssertions.assertThat(consumerEndpoint).isNotNull();\n\t\tAssertions.assertThat(extendedConsumerProperties.getExtension().getGroup())\n\t\t\t\t.isEqualTo(RocketMQConst.DEFAULT_GROUP + \"_test\");\n\t}\n\n\t@Test\n\tpublic void createDLQAnymousConsumerEndpoint() throws Exception {\n\t\tTestConsumerDestination destination = new TestConsumerDestination(\"%DLQ%test\");\n\t\tAssertions.assertThatThrownBy(() -> {\n\t\t\tMessageProducer consumerEndpoint = binder.createConsumerEndpoint(destination, null,\n\t\t\t\t\tnew ExtendedConsumerProperties<>(new RocketMQConsumerProperties()));\n\t\t});\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@ImportAutoConfiguration({ ExtendedBindingHandlerMappingsProviderConfiguration.class,\n\t\t\tRocketMQBinderAutoConfiguration.class})\n\tpublic static class TestConfig {\n\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageConverterSupportTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQMessageConverterSupport;\nimport org.apache.rocketmq.common.message.MessageConst;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.messaging.Message;\nimport org.springframework.messaging.support.MessageBuilder;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Sorie\n */\npublic class RocketMQMessageConverterSupportTest {\n\n\t@Test\n\tpublic void convertMessage2MQBlankHeaderTest() {\n\t\tString destination = \"test\";\n\t\tMessage message = MessageBuilder.withPayload(\"msg\")\n\t\t\t\t.setHeader(MessageConst.PROPERTY_TAGS, \"a\")\n\t\t\t\t.setHeader(\"test\", \"\")\n\t\t\t\t.build();\n\t\torg.apache.rocketmq.common.message.Message rkmqMsg =\n\t\t\t\tRocketMQMessageConverterSupport.convertMessage2MQ(destination, message);\n\t\tString testProp = rkmqMsg.getProperty(\"test\");\n\t\tString tagProp = rkmqMsg.getProperty(MessageConst.PROPERTY_TAGS);\n\t\tassertThat(testProp).isNull();\n\t\tassertThat(tagProp).isEqualTo(\"a\");\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/TestConsumerDestination.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq;\n\nimport org.springframework.cloud.stream.provisioning.ConsumerDestination;\n\npublic class TestConsumerDestination implements ConsumerDestination {\n\tprivate String name;\n\n\tpublic TestConsumerDestination(String name) {\n\t\tthis.name = name;\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn name;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/aot/hint/RocketMQConsumerPropertiesHintsTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.aot.hint;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Method;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.aot.hint.RuntimeHints;\nimport org.springframework.aot.hint.predicate.RuntimeHintsPredicates;\nimport org.springframework.util.ReflectionUtils;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author ChengPu raozihao\n */\npublic class RocketMQConsumerPropertiesHintsTests {\n\n\t@Test\n\tpublic void shouldRegisterHints() {\n\t\tConstructor<RocketMQConsumerProperties> constructor;\n\t\ttry {\n\t\t\tconstructor = RocketMQConsumerProperties.class.getConstructor();\n\t\t}\n\t\tcatch (NoSuchMethodException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\tMethod setMessageModel = ReflectionUtils.findMethod(RocketMQConsumerProperties.class, \"setMessageModel\", String.class);\n\t\tMethod getPush = ReflectionUtils.findMethod(RocketMQConsumerProperties.class, \"getPush\");\n\t\tMethod setSubscription = ReflectionUtils.findMethod(RocketMQConsumerProperties.class, \"setSubscription\", String.class);\n\t\tRuntimeHints hints = new RuntimeHints();\n\t\tnew RocketMQConsumerPropertiesHints().registerHints(hints, getClass().getClassLoader());\n\t\tassertThat(RuntimeHintsPredicates.reflection().onConstructor(constructor)).accepts(hints);\n\t\tassertThat(RuntimeHintsPredicates.reflection().onMethod(setMessageModel)).accepts(hints);\n\t\tassertThat(RuntimeHintsPredicates.reflection().onMethod(getPush)).accepts(hints);\n\t\tassertThat(RuntimeHintsPredicates.reflection().onMethod(setSubscription)).accepts(hints);\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/aot/hint/RocketMQSpecificPropertiesProviderHintsTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.aot.hint;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Method;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQSpecificPropertiesProvider;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.aot.hint.RuntimeHints;\nimport org.springframework.aot.hint.predicate.RuntimeHintsPredicates;\nimport org.springframework.util.ReflectionUtils;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author ChengPu raozihao\n */\npublic class RocketMQSpecificPropertiesProviderHintsTests {\n\n\t@Test\n\tpublic void shouldRegisterHints() {\n\t\tConstructor<RocketMQSpecificPropertiesProvider> constructor;\n\t\ttry {\n\t\t\tconstructor = RocketMQSpecificPropertiesProvider.class.getConstructor();\n\t\t}\n\t\tcatch (NoSuchMethodException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\tMethod getConsumer = ReflectionUtils.findMethod(RocketMQSpecificPropertiesProvider.class, \"getConsumer\");\n\t\tMethod setConsumer = ReflectionUtils.findMethod(RocketMQSpecificPropertiesProvider.class, \"setConsumer\", RocketMQConsumerProperties.class);\n\t\tMethod getProducer = ReflectionUtils.findMethod(RocketMQSpecificPropertiesProvider.class, \"getProducer\");\n\t\tMethod setProducer = ReflectionUtils.findMethod(RocketMQSpecificPropertiesProvider.class, \"setProducer\", RocketMQProducerProperties.class);\n\t\tRuntimeHints hints = new RuntimeHints();\n\t\tnew RocketMQSpecificPropertiesProviderHints().registerHints(hints, getClass().getClassLoader());\n\t\tassertThat(RuntimeHintsPredicates.reflection().onConstructor(constructor)).accepts(hints);\n\t\tassertThat(RuntimeHintsPredicates.reflection().onMethod(getConsumer)).accepts(hints);\n\t\tassertThat(RuntimeHintsPredicates.reflection().onMethod(setConsumer)).accepts(hints);\n\t\tassertThat(RuntimeHintsPredicates.reflection().onMethod(getProducer)).accepts(hints);\n\t\tassertThat(RuntimeHintsPredicates.reflection().onMethod(setProducer)).accepts(hints);\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/nacos-tests/nacos-config-test/src/test/resources/docker/nacos-compose-test.yml",
    "content": ""
  },
  {
    "path": "spring-cloud-alibaba-tests/nacos-tests/nacos-discovery-test/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>nacos-tests</artifactId>\n        <groupId>com.alibaba.cloud</groupId>\n        <version>${revision}</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>nacos-discovery-test</artifactId>\n    <name>Nacos Discovery Test</name>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-loadbalancer</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-openfeign</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-alibaba-test-support</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n</project>"
  },
  {
    "path": "spring-cloud-alibaba-tests/nacos-tests/nacos-discovery-test/src/main/java/com/alibaba/cloud/tests/nacos/discovery/NacosDiscoveryTestApp.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.tests.nacos.discovery;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.web.server.servlet.context.ServletWebServerInitializedEvent;\nimport org.springframework.cloud.client.loadbalancer.LoadBalanced;\nimport org.springframework.cloud.openfeign.EnableFeignClients;\nimport org.springframework.cloud.openfeign.FeignClient;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Profile;\nimport org.springframework.context.event.EventListener;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n *\n * @author freeman\n */\n@SpringBootApplication\n@EnableFeignClients\npublic class NacosDiscoveryTestApp {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(NacosDiscoveryTestApp.class, args);\n\t}\n\n\t@Bean\n\t@LoadBalanced\n\t@Profile(\"service-1\")\n\tRestTemplate restTemplate() {\n\t\treturn new RestTemplate();\n\t}\n\n\t@RestController\n\t@Profile(\"service-2\")\n\tstatic class Controller {\n\t\tint port;\n\n\t\t@GetMapping\n\t\tpublic Object get() {\n\t\t\treturn port;\n\t\t}\n\n\t\t@GetMapping(\"/{ok}\")\n\t\tpublic Object pass(@PathVariable Boolean ok) {\n\t\t\tif (ok) {\n\t\t\t\treturn \"ok\";\n\t\t\t}\n\t\t\tthrow new RuntimeException(\"not ok!\");\n\t\t}\n\n\t\t@EventListener\n\t\tpublic void onApplicationEvent(ServletWebServerInitializedEvent event) {\n\t\t\tport = event.getWebServer().getPort();\n\t\t}\n\t}\n\n\t@FeignClient(value = \"service-2\", fallback = Fallback.class)\n\tinterface Service2Client {\n\t\t@GetMapping\n\t\tObject get();\n\n\t\t@GetMapping(\"/{ok}\")\n\t\tString pass(@PathVariable Boolean ok);\n\t}\n\n\t@Component\n\tstatic class Fallback implements Service2Client {\n\t\t@Override\n\t\tpublic Object get() {\n\t\t\treturn \"shouldn't use this !\";\n\t\t}\n\n\t\t@Override\n\t\tpublic String pass(Boolean ok) {\n\t\t\treturn \"fallback\";\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/nacos-tests/nacos-discovery-test/src/test/java/com/alibaba/cloud/tests/nacos/discovery/NacosDiscoveryTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.tests.nacos.discovery;\n\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.List;\n\nimport com.alibaba.cloud.testsupport.ContainerStarter;\nimport com.alibaba.cloud.testsupport.HasDockerAndItEnabled;\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\nimport org.testcontainers.containers.GenericContainer;\nimport org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper;\n\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.boot.web.server.context.WebServerApplicationContext;\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.cloud.client.discovery.DiscoveryClient;\nimport org.springframework.context.ConfigurableApplicationContext;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.client.RestTemplate;\n\nimport static com.alibaba.cloud.tests.nacos.discovery.NacosDiscoveryTestApp.Service2Client;\nimport static com.alibaba.cloud.testsupport.Tester.justDo;\nimport static com.alibaba.cloud.testsupport.Tester.testFunction;\nimport static java.util.function.Predicate.isEqual;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\n\n/**\n *\n *\n * @author freeman\n */\n@HasDockerAndItEnabled\npublic class NacosDiscoveryTest {\n\n\tstatic GenericContainer nacos;\n\tstatic ConfigurableApplicationContext service1 = new SpringApplicationBuilder(\n\t\t\tNacosDiscoveryTestApp.class).profiles(\"service-1\").run();\n\tstatic ConfigurableApplicationContext service2_0 = new SpringApplicationBuilder(\n\t\t\tNacosDiscoveryTestApp.class).profiles(\"service-2\").run();\n\tstatic ConfigurableApplicationContext service2_1 = new SpringApplicationBuilder(\n\t\t\tNacosDiscoveryTestApp.class).profiles(\"service-2\").run();\n\n\tstatic {\n\t\tnacos = ContainerStarter.startNacos();\n\n\t\t// wait nacos started\n\t\tjustDo(() -> Thread.sleep(4000L));\n\t}\n\n\tstatic {\n\t\tString serverAddr = \"localhost:\" + nacos.getMappedPort(8848);\n\t\tSystem.setProperty(\"spring.cloud.nacos.discovery.server-addr\", serverAddr);\n\t}\n\n\t@BeforeAll\n\tstatic void init() {\n\t\t// give nacos a break\n\t\tjustDo(() -> Thread.sleep(1000L));\n\t}\n\n\t@AfterAll\n\tstatic void stop() {\n\t\tservice1.stop();\n\t\tservice2_0.stop();\n\t\tservice2_1.stop();\n\t}\n\n\t@Test\n\tpublic void testServiceDiscovery() {\n\t\ttestFunction(\"Service discovery\", () -> {\n\t\t\tDiscoveryClient discoveryClient = service1.getBean(DiscoveryClient.class);\n\t\t\tList<ServiceInstance> instances = discoveryClient.getInstances(\"service-2\");\n\t\t\tassertThat(instances).hasSize(2);\n\t\t});\n\t}\n\n\t@Test\n\tpublic void testServiceDiscoveryWithRestTemplate() {\n\t\ttestFunction(\"Service discovery with RestTemplate\", () -> {\n\t\t\tRestTemplate restTemplate = service1.getBean(RestTemplate.class);\n\t\t\tassertThatThrownBy(() -> service2_0.getBean(RestTemplate.class));\n\n\t\t\t// default using RR\n\t\t\tList<Object> list1 = new ArrayList<>();\n\t\t\tList<Object> list2 = new ArrayList<>();\n\t\t\tfor (int i = 0; i < 20; i++) {\n\t\t\t\tResponseEntity<String> response = restTemplate\n\t\t\t\t\t\t.getForEntity(\"http://service-2\", String.class);\n\t\t\t\tif (i % 2 != 0) {\n\t\t\t\t\tlist1.add(response.getBody());\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tlist2.add(response.getBody());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tassertThat(list1).hasSize(10);\n\t\t\tassertThat(list1.stream().allMatch(isEqual(list1.get(0)))).isTrue();\n\t\t\tassertThat(list2).hasSize(10);\n\t\t\tassertThat(list2.stream().allMatch(isEqual(list2.get(0)))).isTrue();\n\t\t});\n\t}\n\n\t@Test\n\tpublic void testServiceDiscoveryWithFeignClient() {\n\t\ttestFunction(\"Service discovery with FeignClient\", () -> {\n\t\t\tService2Client service2Client = service1.getBean(Service2Client.class);\n\n\t\t\t// default using RR\n\t\t\tList<Object> list1 = new ArrayList<>();\n\t\t\tList<Object> list2 = new ArrayList<>();\n\t\t\tfor (int i = 0; i < 20; i++) {\n\t\t\t\tObject result = service2Client.get();\n\t\t\t\tif (i % 2 != 0) {\n\t\t\t\t\tlist1.add(result);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tlist2.add(result);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tassertThat(list1).hasSize(10);\n\t\t\tassertThat(list1.stream().allMatch(isEqual(list1.get(0)))).isTrue();\n\t\t\tassertThat(list2).hasSize(10);\n\t\t\tassertThat(list2.stream().allMatch(isEqual(list2.get(0)))).isTrue();\n\t\t});\n\t}\n\n\t@Test\n\tpublic void testServiceDiscoveryWithFeignClientUsingSentinelCircuitBreaker() {\n\t\ttestFunction(\"Service discovery with FeignClient using Sentinel Circuit Breaker\",\n\t\t\t\t() -> {\n\t\t\t\t\tService2Client service2Client = service1\n\t\t\t\t\t\t\t.getBean(Service2Client.class);\n\n\t\t\t\t\tList<Object> passResult = new ArrayList<>();\n\t\t\t\t\tList<Object> fallbackResult = new ArrayList<>();\n\t\t\t\t\tfor (int i = 0; i < 10; i++) {\n\t\t\t\t\t\tpassResult.add(service2Client.pass(true));\n\t\t\t\t\t\tfallbackResult.add(service2Client.pass(false));\n\t\t\t\t\t}\n\n\t\t\t\t\tassertThat(passResult.stream().allMatch(isEqual(\"ok\"))).isTrue();\n\t\t\t\t\tassertThat(fallbackResult.stream().allMatch(isEqual(\"fallback\")))\n\t\t\t\t\t\t\t.isTrue();\n\t\t\t\t});\n\t}\n\n\t@Test\n\tpublic void testServiceDiscoveryActuatorEndpoint() {\n\t\ttestFunction(\"Service discovery actuator endpoint\", () -> {\n\n\t\t\tWebServerApplicationContext webServerApplicationContext = (WebServerApplicationContext) service1;\n\t\t\tint port = webServerApplicationContext.getWebServer().getPort();\n\n\t\t\tString response = new RestTemplate().getForEntity(\n\t\t\t\t\tString.format(\"http://127.0.0.1:%d/actuator/nacosdiscovery\", port),\n\t\t\t\t\tString.class).getBody();\n\n\t\t\tLinkedHashMap map = new ObjectMapper().readValue(response,\n\t\t\t\t\tLinkedHashMap.class);\n\n\t\t\tassertThat(map.containsKey(\"subscribe\")).isTrue();\n\t\t\tassertThat(map.containsKey(\"NacosDiscoveryProperties\")).isTrue();\n\t\t});\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/nacos-tests/nacos-discovery-test/src/test/resources/application-service-1.yml",
    "content": "server:\n  port: 0\n  tomcat:\n    threads:\n      min-spare: 2\n      max: 10\nspring:\n  application:\n    name: service-1\n  cloud:\n    nacos:\n      discovery:\n        server-addr: localhost:8848\nfeign:\n  circuitbreaker:\n    enabled: true\n\nmanagement:\n  endpoints:\n    web:\n      exposure:\n        include: '*'\n\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/nacos-tests/nacos-discovery-test/src/test/resources/application-service-2.yml",
    "content": "server:\n  port: 0\n  tomcat:\n    threads:\n      min-spare: 4\n      max: 10\nspring:\n  application:\n    name: service-2\n  cloud:\n    nacos:\n      discovery:\n        server-addr: localhost:8848\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/nacos-tests/nacos-discovery-test/src/test/resources/docker/nacos-compose-test.yml",
    "content": "services:\n  nacos:\n    image: nacos/nacos-server:v3.1.0\n    container_name: nacos-standalone\n    environment:\n      - PREFER_HOST_MODE=hostname\n      - MODE=standalone\n    ports:\n      - \"8848:8848\"\n      - \"9848:9848\"\n    healthcheck:\n      test: \"curl --fail http://127.0.0.1:8848/nacos/v1/console/health/liveness || exit 1\"\n      interval: 5s"
  },
  {
    "path": "spring-cloud-alibaba-tests/nacos-tests/nacos-discovery-test/src/test/resources/nacos/nacos-config-refresh.yml",
    "content": "configdata:\n  user:\n    age: 22\n    name: freeman1123\n    map:\n      hobbies:\n        - art\n        - programming\n        - movie\n      intro: Hello, I'm freeman\n      extra: yo~\n    users:\n      - name: dad\n        age: 20\n      - name: mom\n        age: 18"
  },
  {
    "path": "spring-cloud-alibaba-tests/nacos-tests/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <modules>\n        <module>nacos-discovery-test</module>\n    </modules>\n    <parent>\n        <artifactId>spring-cloud-alibaba-tests</artifactId>\n        <groupId>com.alibaba.cloud</groupId>\n        <version>${revision}</version>\n    </parent>\n    <packaging>pom</packaging>\n\n    <artifactId>nacos-tests</artifactId>\n    <name>Nacos Tests</name>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-bootstrap</artifactId>\n            <scope>compile</scope>\n        </dependency>\n    </dependencies>\n\n</project>"
  },
  {
    "path": "spring-cloud-alibaba-tests/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <artifactId>spring-cloud-alibaba</artifactId>\n        <groupId>com.alibaba.cloud</groupId>\n        <version>${revision}</version>\n    </parent>\n    <artifactId>spring-cloud-alibaba-tests</artifactId>\n    <name>Spring Cloud Alibaba Tests</name>\n    <packaging>pom</packaging>\n\n    <modules>\n        <module>spring-cloud-alibaba-test-support</module>\n        <module>nacos-tests</module>\n        <!-- todo spring boot 3.0 upgrade: wait to support jdk17 and spring cloud stream -->\n        <!-- <module>rocketmq-tests</module> -->\n        <module>sentinel-tests</module>\n    </modules>\n\n    <properties>\n        <testcontainers.version>1.16.3</testcontainers.version>\n    </properties>\n\n    <dependencyManagement>\n        <dependencies>\n            <dependency>\n                <groupId>com.alibaba.cloud</groupId>\n                <artifactId>spring-cloud-alibaba-test-support</artifactId>\n                <version>${project.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.testcontainers</groupId>\n                <artifactId>testcontainers-bom</artifactId>\n                <version>${testcontainers.version}</version>\n                <type>pom</type>\n                <scope>import</scope>\n            </dependency>\n        </dependencies>\n    </dependencyManagement>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-deploy-plugin</artifactId>\n                <version>${maven-deploy-plugin.version}</version>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>"
  },
  {
    "path": "spring-cloud-alibaba-tests/rocketmq-tests/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n\n  <name>Rocketmq Test</name>\n\n  <modules>\n    <module>rocketmq-stream-test</module>\n  </modules>\n  <parent>\n    <artifactId>spring-cloud-alibaba-tests</artifactId>\n    <groupId>com.alibaba.cloud</groupId>\n    <version>${revision}</version>\n  </parent>\n  <packaging>pom</packaging>\n  <artifactId>rocketmq-tests</artifactId>\n\n  <properties>\n    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n    <spring-cloud-stream-test-support.version>4.0.0</spring-cloud-stream-test-support.version>\n  </properties>\n\n  <dependencies>\n    <dependency>\n      <groupId>junit</groupId>\n      <artifactId>junit</artifactId>\n      <version>4.13.1</version>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.springframework.cloud</groupId>\n      <artifactId>spring-cloud-stream-test-support</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <dependencyManagement>\n   <dependencies>\n       <dependency>\n           <groupId>org.springframework.cloud</groupId>\n           <artifactId>spring-cloud-stream-test-support</artifactId>\n           <version>${spring-cloud-stream-test-support.version}</version>\n       </dependency>\n   </dependencies>\n  </dependencyManagement>\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/rocketmq-tests/rocketmq-stream-test/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>rocketmq-tests</artifactId>\n    <groupId>com.alibaba.cloud</groupId>\n    <version>${revision}</version>\n  </parent>\n\n  <artifactId>rocketmq-stream-test</artifactId>\n  <modelVersion>4.0.0</modelVersion>\n  <name>Rocketmq Stream Test</name>\n\n  <dependencies>\n    <dependency>\n      <groupId>org.springframework.boot</groupId>\n      <artifactId>spring-boot-configuration-processor</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>com.alibaba.cloud</groupId>\n      <artifactId>spring-cloud-alibaba-test-support</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>com.alibaba.cloud</groupId>\n      <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>\n    </dependency>\n  </dependencies>\n\n  <build>\n    <plugins>\n      <plugin>\n        <artifactId>maven-jar-plugin</artifactId>\n        <version>3.0.3</version>\n        <executions>\n          <execution>\n            <goals>\n              <goal>test-jar</goal>\n            </goals>\n          </execution>\n        </executions>\n      </plugin>\n\n    </plugins>\n  </build>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/rocketmq-tests/rocketmq-stream-test/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketmqStreamApplication.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class RocketmqStreamApplication {\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(RocketmqStreamApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/rocketmq-tests/rocketmq-stream-test/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate.RocketMQBinderAutoConfiguration;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties;\nimport com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQExtendedBindingProperties;\nimport com.alibaba.cloud.testsupport.SpringCloudAlibaba;\nimport com.alibaba.cloud.testsupport.TestExtend;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.AutoConfigurations;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.boot.test.context.runner.ApplicationContextRunner;\nimport org.springframework.context.annotation.Configuration;\n\nimport static com.alibaba.cloud.testsupport.Constant.TIME_OUT;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE;\n\n@SpringCloudAlibaba(composeFiles = \"docker/rocket-compose-test.yml\", serviceName = \"rocketmq-standalone\")\n@TestExtend(time = 6 * TIME_OUT)\n@SpringBootTest(classes = RocketMQAutoConfigurationTests.TestConfig.class, webEnvironment = NONE, properties = {\n\t\t\"spring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876,127.0.0.1:9877\",\n\t\t\"spring.cloud.stream.bindings.output.destination=TopicOrderTest\",\n\t\t\"spring.cloud.stream.bindings.output.content-type=application/json\",\n\n\t\t\"spring.cloud.stream.bindings.input1.destination=TopicOrderTest\",\n\t\t\"spring.cloud.stream.bindings.input1.content-type=application/json\",\n\t\t\"spring.cloud.stream.bindings.input1.group=test-group1\",\n\t\t\"spring.cloud.stream.rocketmq.bindings.input1.consumer.push.orderly=true\",\n\t\t\"spring.cloud.stream.bindings.input1.consumer.maxAttempts=1\",\n\t\t\"spring.cloud.stream.bindings.input2.destination=TopicOrderTest\",\n\t\t\"spring.cloud.stream.bindings.input2.content-type=application/json\",\n\t\t\"spring.cloud.stream.bindings.input2.group=test-group2\",\n\t\t\"spring.cloud.stream.rocketmq.bindings.input2.consumer.push.orderly=false\",\n\t\t\"spring.cloud.stream.rocketmq.bindings.input2.consumer.subscription=tag1\" })\npublic class RocketMQAutoConfigurationTests {\n\n\t@Autowired\n\tprivate RocketMQBinderConfigurationProperties binderConfigurationProperties;\n\t@Autowired\n\tprivate RocketMQExtendedBindingProperties bindingProperties;\n\n\tprivate final ApplicationContextRunner contextRunner = new ApplicationContextRunner()\n\t\t\t.withConfiguration(\n\t\t\t\t\tAutoConfigurations.of(RocketMQBinderAutoConfiguration.class));\n\n\t@BeforeAll\n\tpublic static void setUp() {\n\n\t}\n\n\t@BeforeEach\n\tpublic void prepare() {\n\n\t}\n\n\t@Test\n\tpublic void testProperties() {\n\t\tthis.contextRunner.run(context -> {\n\t\t\tassertThat(binderConfigurationProperties.getNameServer())\n\t\t\t\t\t.isEqualTo(\"127.0.0.1:9876,127.0.0.1:9877\");\n\t\t\tassertThat(bindingProperties.getExtendedConsumerProperties(\"input2\")\n\t\t\t\t\t.getSubscription()).isEqualTo(\"tag1\");\n\t\t\tassertThat(bindingProperties.getExtendedConsumerProperties(\"input2\").getPush()\n\t\t\t\t\t.getOrderly()).isFalse();\n\t\t\tassertThat(bindingProperties.getExtendedConsumerProperties(\"input1\").getPush()\n\t\t\t\t\t.getOrderly()).isTrue();\n\t\t});\n\t}\n\n\t@Configuration\n\t@EnableAutoConfiguration\n\t@ImportAutoConfiguration({RocketMQBinderAutoConfiguration.class })\n\tpublic static class TestConfig {\n\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/rocketmq-tests/rocketmq-stream-test/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketmqProduceAndConsumerTests.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.BlockingQueue;\n\nimport com.alibaba.cloud.stream.binder.rocketmq.fixture.RocketmqBinderProcessor;\nimport com.alibaba.cloud.testsupport.SpringCloudAlibaba;\nimport com.alibaba.cloud.testsupport.TestExtend;\nimport com.alibaba.fastjson.JSON;\nimport org.apache.rocketmq.common.message.MessageConst;\nimport org.hamcrest.MatcherAssert;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;\nimport org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;\nimport org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.cloud.stream.test.binder.MessageCollector;\nimport org.springframework.messaging.Message;\nimport org.springframework.messaging.MessageChannel;\nimport org.springframework.messaging.support.GenericMessage;\nimport org.springframework.test.annotation.DirtiesContext;\n\nimport static com.alibaba.cloud.testsupport.Constant.TIME_OUT;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE;\nimport static org.springframework.cloud.stream.test.matcher.MessageQueueMatcher.receivesPayloadThat;\n\n@SpringCloudAlibaba(composeFiles = \"docker/rocket-compose-test.yml\", serviceName = \"rocketmq-standalone\")\n@TestExtend(time = 6 * TIME_OUT)\n@DirtiesContext\n@ImportAutoConfiguration(value = {}, exclude = { DataSourceAutoConfiguration.class,\n\t\tTransactionAutoConfiguration.class,\n\t\tDataSourceTransactionManagerAutoConfiguration.class })\n@SpringBootTest(classes = RocketmqBinderProcessor.class, webEnvironment = NONE, properties = {\n\t\t\"spring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876,127.0.0.1:9877\",\n\t\t\"spring.cloud.stream.rocketmq.binder.group=flaky-group\",\n\t\t// \"spring.cloud.stream.rocketmq.binder.consumer-group=flaky-group\",\n\t\t// \"spring.cloud.stream.pollable-source=pollable\",\n\t\t\"spring.cloud.stream.bindings.uppercaseFunction-out-0.destination=TopicOrderTest\",\n\t\t\"spring.cloud.stream.bindings.uppercaseFunction-out-0.content-type=application/json\",\n\t\t\"spring.cloud.stream.bindings.uppercaseFunction-out-0.group=test-group1\",\n\t\t\"spring.cloud.stream.bindings.uppercaseFunction-in-0.destination=TopicOrderTest\",\n\t\t\"spring.cloud.stream.bindings.uppercaseFunction-in-0.content-type=application/json\",\n\t\t\"spring.cloud.stream.bindings.uppercaseFunction-in-0.group=test-group1\",\n\t\t\"spring.cloud.stream.bindings.uppercaseFunction-in-0.consumer.push.orderly=true\",\n\t\t\"spring.cloud.stream.bindings.uppercaseFunction-in-0.consumer.maxAttempts=1\" })\npublic class RocketmqProduceAndConsumerTests {\n\n\t@Autowired\n\tprivate MessageCollector collector;\n\n\t@Autowired\n\t@Qualifier(\"uppercaseFunction-in-0\")\n\tprivate MessageChannel input1;\n\n\t@Autowired\n\t@Qualifier(\"uppercaseFunction-out-0\")\n\tprivate MessageChannel output;\n\n\t@BeforeAll\n\tpublic static void prepare() {\n\n\t}\n\n\t@BeforeEach\n\tpublic void setup() {\n\t\tString key = \"KEY\";\n\t\tString messageId = \"1\";\n\t\tMap<String, Object> headers = new HashMap<>();\n\t\theaders.put(MessageConst.PROPERTY_KEYS, key);\n\t\theaders.put(MessageConst.PROPERTY_TAGS, \"TagA\");\n\t\theaders.put(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID, messageId);\n\t\tMessage<String> msg = new GenericMessage(JSON.toJSONString(\"Hello RocketMQ\"),\n\t\t\t\theaders);\n\t\tinput1.send(msg);\n\t}\n\n\t@Test\n\tpublic void testConsumeAndProduce() throws Exception {\n\t\tBlockingQueue<Message<?>> messages = this.collector.forChannel(this.output);\n\n\t\tMatcherAssert.assertThat(messages, receivesPayloadThat(is(\"\\\"HELLO ROCKETMQ\\\"\")));\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/rocketmq-tests/rocketmq-stream-test/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/fixture/RocketmqBinderProcessor.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.stream.binder.rocketmq.fixture;\n\nimport java.util.function.Function;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.annotation.Bean;\n\n@SpringBootApplication\npublic class RocketmqBinderProcessor {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(RocketmqBinderProcessor.class, args);\n\t}\n\n\t@Bean\n\tpublic Function<String, String> uppercaseFunction() {\n\t\treturn String::toUpperCase;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/rocketmq-tests/rocketmq-stream-test/src/test/resources/docker/data/broker/conf/broker.conf",
    "content": "brokerClusterName = DefaultCluster\nbrokerName = broker-a\nbrokerId = 0\ndeleteWhen = 04\nfileReservedTime = 48\nbrokerRole = ASYNC_MASTER\nflushDiskType = ASYNC_FLUSH\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/rocketmq-tests/rocketmq-stream-test/src/test/resources/docker/data1/broker/conf/broker.conf",
    "content": "brokerClusterName = DefaultCluster\nbrokerName = broker-b\nbrokerId = 0\ndeleteWhen = 04\nfileReservedTime = 48\nbrokerRole = ASYNC_MASTER\nflushDiskType = ASYNC_FLUSH\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/rocketmq-tests/rocketmq-stream-test/src/test/resources/docker/rocket-compose-test.yml",
    "content": "services:\n  #Service for nameserver\n  namesrv:\n    image: apache/rocketmq:4.9.3\n    container_name: rmqnamesrv\n    ports:\n      - 9876:9876\n    volumes:\n      - ./data/namesrv/logs:/home/rocketmq/logs\n    command: sh mqnamesrv\n\n  #Service for broker\n  broker:\n    image: apache/rocketmq:4.9.3\n    container_name: rmqbroker\n    links:\n      - namesrv\n    ports:\n      - 10909:10909\n      - 10911:10911\n      - 10912:10912\n    environment:\n      - NAMESRV_ADDR=namesrv:9876\n    volumes:\n      - ./data/broker/logs:/home/rocketmq/logs\n      - ./data/broker/store:/home/rocketmq/store\n      - ./data/broker/conf/broker.conf:/opt/rocketmq-4.9.3/conf/broker.conf\n    command: sh mqbroker -c /opt/rocketmq-4.9.3/conf/broker.conf\n\n  #Service for another broker -- broker1\n  broker1:\n    image: apache/rocketmq:4.9.3\n    container_name: rmqbroker-b\n    links:\n      - namesrv\n    ports:\n      - 10929:10909\n      - 10931:10911\n      - 10932:10912\n    environment:\n      - NAMESRV_ADDR=namesrv:9876\n    volumes:\n      - ./data1/broker/logs:/home/rocketmq/logs\n      - ./data1/broker/store:/home/rocketmq/store\n      - ./data1/broker/conf/broker.conf:/opt/rocketmq-4.9.3/conf/broker.conf\n    command: sh mqbroker -c /opt/rocketmq-4.9.3/conf/broker.conf\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/sentinel-tests/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-tests</artifactId>\n        <version>${revision}</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    <artifactId>sentinel-tests</artifactId>\n    <packaging>pom</packaging>\n    <name>Sentinel Tests</name>\n    <modules>\n        <module>sentinel-flowcontrol-test</module>\n        <module>sentinel-degrade-test</module>\n    </modules>\n\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/sentinel-tests/sentinel-degrade-test/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n    <parent>\n        <artifactId>sentinel-tests</artifactId>\n        <groupId>com.alibaba.cloud</groupId>\n        <version>${revision}</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    <artifactId>sentinel-degrade-test</artifactId>\n    <name>Sentinel Degrade Test</name>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-alibaba-test-support</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-restclient</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-resttestclient</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/sentinel-tests/sentinel-degrade-test/src/main/java/com/alibaba/cloud/tests/sentinel/degrade/SentinelDegradeTestApp.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.tests.sentinel.degrade;\n\nimport java.util.Arrays;\n\nimport com.alibaba.csp.sentinel.annotation.SentinelResource;\nimport com.alibaba.csp.sentinel.slots.block.RuleConstant;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;\nimport com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.context.event.ApplicationReadyEvent;\nimport org.springframework.context.event.EventListener;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author Freeman\n */\n@SpringBootApplication\n@RestController\npublic class SentinelDegradeTestApp {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(SentinelDegradeTestApp.class, args);\n\t}\n\n\t@RequestMapping(\"/degrade\")\n\t@SentinelResource(value = \"/degrade\", fallback = \"fallback\")\n\tpublic String degrade() {\n\t\tthrow new RuntimeException(\"Ops, something wrong!\");\n\t}\n\n\tpublic static String fallback() {\n\t\treturn \"fallback\";\n\t}\n\n\t@EventListener(ApplicationReadyEvent.class)\n\tpublic void onApplicationReady() {\n\t\tDegradeRule degradeRule = new DegradeRule();\n\t\tdegradeRule.setResource(\"/degrade\");\n\t\tdegradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);\n\t\tdegradeRule.setMinRequestAmount(1);\n\t\tdegradeRule.setStatIntervalMs(2);\n\t\tdegradeRule.setTimeWindow(1);\n\t\tdegradeRule.setCount(1);\n\t\tDegradeRuleManager.loadRules(Arrays.asList(degradeRule));\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/sentinel-tests/sentinel-degrade-test/src/main/resources/application.yml",
    "content": "server:\n  port: 8080\nspring:\n  application:\n    name: sentinel-flowcontrol-test"
  },
  {
    "path": "spring-cloud-alibaba-tests/sentinel-tests/sentinel-degrade-test/src/test/java/com/alibaba/cloud/tests/sentinel/degrade/SentinelDegradeTestAppTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.tests.sentinel.degrade;\n\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.resttestclient.TestRestTemplate;\nimport org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.boot.test.web.server.LocalServerPort;\nimport org.springframework.http.ResponseEntity;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;\n\n@AutoConfigureTestRestTemplate\n@SpringBootTest(webEnvironment = RANDOM_PORT)\nclass SentinelDegradeTestAppTest {\n\n\t@LocalServerPort\n\tint port;\n\n\t@Autowired\n\tTestRestTemplate rest;\n\n\t@Test\n\tpublic void testDegradeRule() {\n\t\tResponseEntity<String> res = rest\n\t\t\t\t.getForEntity(\"http://localhost:\" + port + \"/degrade\", String.class);\n\n\t\tassertThat(res.getBody()).contains(\"fallback\");\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/sentinel-tests/sentinel-flowcontrol-test/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>sentinel-tests</artifactId>\n        <version>${revision}</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    <artifactId>sentinel-flowcontrol-test</artifactId>\n    <name>Sentinel Flowcontrol Test</name>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.cloud</groupId>\n            <artifactId>spring-cloud-alibaba-test-support</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-restclient</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-resttestclient</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n</project>\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/sentinel-tests/sentinel-flowcontrol-test/src/main/java/com/alibaba/cloud/tests/sentinel/degrade/SentinelFlowControlTestApp.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.tests.sentinel.degrade;\n\nimport java.util.Arrays;\n\nimport com.alibaba.csp.sentinel.annotation.SentinelResource;\nimport com.alibaba.csp.sentinel.slots.block.RuleConstant;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRule;\nimport com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.context.event.ApplicationReadyEvent;\nimport org.springframework.context.event.EventListener;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport static com.alibaba.cloud.tests.sentinel.degrade.Util.FLOW_CONTROL_NOT_TRIGGERED;\nimport static com.alibaba.cloud.tests.sentinel.degrade.Util.FLOW_CONTROL_TRIGGERED;\n\n/**\n * @author Freeman\n */\n@SpringBootApplication\n@RestController\npublic class SentinelFlowControlTestApp {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(SentinelFlowControlTestApp.class, args);\n\t}\n\n\t@RequestMapping(FLOW_CONTROL_NOT_TRIGGERED)\n\t@SentinelResource(value = FLOW_CONTROL_NOT_TRIGGERED, defaultFallback = \"fallback\")\n\tpublic String flowControlNotTriggered() {\n\t\treturn \"OK\";\n\t}\n\n\t@RequestMapping(FLOW_CONTROL_TRIGGERED)\n\t@SentinelResource(value = FLOW_CONTROL_TRIGGERED, defaultFallback = \"fallback\")\n\tpublic String flowControlTriggered() {\n\t\treturn \"OK\";\n\t}\n\n\tprivate static String fallback() {\n\t\treturn \"fallback\";\n\t}\n\n\t@EventListener(ApplicationReadyEvent.class)\n\tpublic void onApplicationReady() {\n\t\tFlowRule notTriggeredRule = new FlowRule();\n\t\tnotTriggeredRule.setResource(FLOW_CONTROL_NOT_TRIGGERED);\n\t\tnotTriggeredRule.setGrade(RuleConstant.FLOW_GRADE_QPS);\n\t\tnotTriggeredRule.setCount(4);\n\t\tFlowRule triggeredRule = new FlowRule();\n\t\ttriggeredRule.setResource(FLOW_CONTROL_TRIGGERED);\n\t\ttriggeredRule.setGrade(RuleConstant.FLOW_GRADE_QPS);\n\t\ttriggeredRule.setCount(3);\n\t\tFlowRuleManager.loadRules(Arrays.asList(notTriggeredRule, triggeredRule));\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/sentinel-tests/sentinel-flowcontrol-test/src/main/java/com/alibaba/cloud/tests/sentinel/degrade/Util.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.tests.sentinel.degrade;\n\n/**\n * @author Freeman\n */\npublic final class Util {\n\n\tprivate Util() {\n\t\tthrow new AssertionError(\"No Util instances for you!\");\n\t}\n\n\t/**\n\t * Flow control not triggered.\n\t */\n\tpublic static final String FLOW_CONTROL_NOT_TRIGGERED = \"/flowControlNotTriggered\";\n\t/**\n\t * Flow control triggered.\n\t */\n\tpublic static final String FLOW_CONTROL_TRIGGERED = \"/flowControlTriggered\";\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/sentinel-tests/sentinel-flowcontrol-test/src/main/resources/application.yml",
    "content": "server:\n  port: 8080\nspring:\n  application:\n    name: sentinel-flowcontrol-test"
  },
  {
    "path": "spring-cloud-alibaba-tests/sentinel-tests/sentinel-flowcontrol-test/src/test/java/com/alibaba/cloud/tests/sentinel/degrade/SentinelFlowControlTestAppTest.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.tests.sentinel.degrade;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.junit.jupiter.api.Test;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.resttestclient.TestRestTemplate;\nimport org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.boot.test.web.server.LocalServerPort;\nimport org.springframework.http.ResponseEntity;\n\nimport static com.alibaba.cloud.tests.sentinel.degrade.Util.FLOW_CONTROL_NOT_TRIGGERED;\nimport static com.alibaba.cloud.tests.sentinel.degrade.Util.FLOW_CONTROL_TRIGGERED;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;\n\n@AutoConfigureTestRestTemplate\n@SpringBootTest(webEnvironment = RANDOM_PORT)\nclass SentinelFlowControlTestAppTest {\n\n\t@LocalServerPort\n\tint port;\n\n\t@Autowired\n\tTestRestTemplate rest;\n\n\t@Test\n\tvoid testFlowControl_whenNotTriggered() {\n\t\tfinal int count = 3;\n\t\tList<String> result = new ArrayList<>();\n\n\t\tfor (int i = 0; i < count; i++) {\n\t\t\tResponseEntity<String> res = rest.getForEntity(\n\t\t\t\t\t\"http://localhost:\" + port + FLOW_CONTROL_NOT_TRIGGERED,\n\t\t\t\t\tString.class);\n\t\t\tresult.add(res.getBody());\n\t\t}\n\n\t\tassertThat(result).doesNotContain(\"fallback\");\n\t}\n\n\t@Test\n\tvoid testFlowControl_whenTriggered() {\n\t\tfinal int count = 3;\n\t\tList<String> result = new ArrayList<>();\n\n\t\tfor (int i = 0; i < count; i++) {\n\t\t\tResponseEntity<String> res = rest.getForEntity(\n\t\t\t\t\t\"http://localhost:\" + port + FLOW_CONTROL_TRIGGERED, String.class);\n\t\t\tresult.add(res.getBody());\n\t\t}\n\n\t\tassertThat(result).containsSequence(\"fallback\");\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/spring-cloud-alibaba-test-support/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <groupId>com.alibaba.cloud</groupId>\n        <artifactId>spring-cloud-alibaba-tests</artifactId>\n        <version>${revision}</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>spring-cloud-alibaba-test-support</artifactId>\n    <name>Spring Cloud Alibaba Test Support</name>\n\n    <properties>\n        <maven.compiler.source>17</maven.compiler.source>\n        <maven.compiler.target>17</maven.compiler.target>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <junit.version>5.10.2</junit.version>\n        <selenium.version>3.141.59</selenium.version>\n        <assertj-core.version>3.25.3</assertj-core.version>\n        <awaitility.version>4.2.2</awaitility.version>\n        <kotlin.version>1.9.24</kotlin.version>\n        <hamcrest.version>3.0</hamcrest.version>\n        <mockito-core.version>4.6.1</mockito-core.version>\n        <visible-assertions.version>2.1.2</visible-assertions.version>\n    </properties>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>compile</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.apache.logging.log4j</groupId>\n            <artifactId>log4j-slf4j2-impl</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.hamcrest</groupId>\n            <artifactId>hamcrest-library</artifactId>\n            <version>${hamcrest.version}</version>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.hamcrest</groupId>\n            <artifactId>hamcrest-core</artifactId>\n            <version>${hamcrest.version}</version>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.testcontainers</groupId>\n            <artifactId>testcontainers</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.testcontainers</groupId>\n            <artifactId>junit-jupiter</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.assertj</groupId>\n            <artifactId>assertj-core</artifactId>\n            <version>${assertj-core.version}</version>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.awaitility</groupId>\n            <artifactId>awaitility</artifactId>\n            <version>${awaitility.version}</version>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n            <version>${mockito-core.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>org.rnorth.visible-assertions</groupId>\n            <artifactId>visible-assertions</artifactId>\n            <version>${visible-assertions.version}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <scope>provided</scope>\n        </dependency>\n    </dependencies>\n\n    <dependencyManagement>\n        <dependencies>\n            <dependency>\n                <groupId>org.junit</groupId>\n                <artifactId>junit-bom</artifactId>\n                <version>${junit.version}</version>\n                <scope>import</scope>\n                <type>pom</type>\n            </dependency>\n            <dependency>\n                <groupId>org.testcontainers</groupId>\n                <artifactId>testcontainers-bom</artifactId>\n                <version>${testcontainers.version}</version>\n                <scope>import</scope>\n                <type>pom</type>\n            </dependency>\n        </dependencies>\n    </dependencyManagement>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-surefire-plugin</artifactId>\n                <version>${maven-surefire-plugin.version}</version>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>"
  },
  {
    "path": "spring-cloud-alibaba-tests/spring-cloud-alibaba-test-support/src/main/java/com/alibaba/cloud/testsupport/Constant.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.testsupport;\n\npublic class Constant {\n\n\t/**\n\t * container timeout.\n\t */\n\tpublic static final long TIME_OUT = 5000;\n\n\t/**\n\t * nacos refresh config.\n\t */\n\tpublic static final String REFRESH_CONFIG = \"nacos-config-refresh.yml\";\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/spring-cloud-alibaba-test-support/src/main/java/com/alibaba/cloud/testsupport/ContainerStarter.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.testsupport;\n\nimport java.io.IOException;\nimport java.util.Collections;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport org.testcontainers.containers.FixedHostPortGenericContainer;\nimport org.testcontainers.containers.GenericContainer;\nimport org.testcontainers.shaded.org.apache.commons.io.FileUtils;\n\nimport org.springframework.core.io.ClassPathResource;\n\n/**\n * Util class for starting the related container.\n *\n * @author freeman\n * @since 2021.0.1.0\n */\npublic class ContainerStarter {\n\n\tprivate static final String ROCKETMQ_BROKER_CONFIG_PATH = \"rocketmq/conf/broker.conf\";\n\n\tprivate static final String NACOS_VERSION = \"1.4.2\";\n\tprivate static final String SENTINEL_VERSION = \"1.8.3\";\n\tprivate static final String ROCKETMQ_VERSION = \"4.9.2\";\n\tprivate static final String SEATA_VERSION = \"1.4.2\";\n\n\tprivate static final Map<String, GenericContainer> nacosMap = new ConcurrentHashMap<>(\n\t\t\t4);\n\tprivate static final Map<String, GenericContainer> rocketmqMap = new ConcurrentHashMap<>(\n\t\t\t4);\n\n\t/**\n\t * Start Nacos container, using default version.\n\t */\n\tpublic static GenericContainer startNacos() {\n\t\treturn startNacos(NACOS_VERSION);\n\t}\n\n\t/**\n\t * Start RocketMQ container, using default version.\n\t */\n\tpublic static GenericContainer startRocketmq() {\n\t\treturn startRocketmq(ROCKETMQ_VERSION);\n\t}\n\n\t/**\n\t * Start Nacos container, using specific version.\n\t * @param version Nacos version\n\t */\n\tpublic static GenericContainer startNacos(String version) {\n\t\tif (!nacosMap.containsKey(version)) {\n\t\t\tGenericContainer nacos = new GenericContainer(\"freemanlau/nacos:\" + version)\n\t\t\t\t\t.withExposedPorts(8848).withEnv(\"MODE\", \"standalone\")\n\t\t\t\t\t.withEnv(\"JVM_XMS\", \"256m\").withEnv(\"JVM_XMX\", \"256m\")\n\t\t\t\t\t.withEnv(\"JVM_XMN\", \"128m\");\n\t\t\tnacos.start();\n\t\t\tnacosMap.put(version, nacos);\n\t\t}\n\t\treturn nacosMap.get(version);\n\t}\n\n\t/**\n\t * Start RocketMQ container, using specific version.\n\t * @param version RocketMQ version\n\t */\n\tpublic static GenericContainer startRocketmq(String version) {\n\t\tif (!rocketmqMap.containsKey(version)) {\n\t\t\tloadHostIp2BrokerConf();\n\t\t\t// this image exposes 4 ports, include namesrv and broker\n\t\t\t// we need use FixedHostPortGenericContainer !\n\t\t\tGenericContainer rocketmq = new FixedHostPortGenericContainer(\n\t\t\t\t\t\"freemanlau/rocketmq:\" + version).withFixedExposedPort(9876, 9876)\n\t\t\t\t\t\t\t.withFixedExposedPort(10909, 10909)\n\t\t\t\t\t\t\t.withFixedExposedPort(10911, 10911)\n\t\t\t\t\t\t\t.withFixedExposedPort(10912, 10912);\n\t\t\trocketmq.withFileSystemBind(getAbsolutePath4BrokerConf(),\n\t\t\t\t\t\"/home/rocketmq/rocketmq-\" + version + \"/conf/broker.conf\");\n\t\t\trocketmq.start();\n\t\t\trocketmqMap.put(version, rocketmq);\n\t\t}\n\t\treturn rocketmqMap.get(version);\n\t}\n\n\tprivate static void loadHostIp2BrokerConf() {\n\t\ttry {\n\t\t\tClassPathResource resource = new ClassPathResource(\n\t\t\t\t\tROCKETMQ_BROKER_CONFIG_PATH);\n\t\t\tFileUtils.writeLines(resource.getFile(),\n\t\t\t\t\tCollections.singletonList(\"brokerIP1 = \" + InetUtil.getHostIp()),\n\t\t\t\t\ttrue);\n\t\t}\n\t\tcatch (IOException e) {\n\t\t\tthrow new RuntimeException(\"load host ip to 'broker.conf' err !\", e);\n\t\t}\n\t}\n\n\tprivate static String getAbsolutePath4BrokerConf() {\n\t\ttry {\n\t\t\tClassPathResource resource = new ClassPathResource(\n\t\t\t\t\tROCKETMQ_BROKER_CONFIG_PATH);\n\t\t\treturn resource.getFile().getAbsolutePath();\n\t\t}\n\t\tcatch (IOException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/spring-cloud-alibaba-test-support/src/main/java/com/alibaba/cloud/testsupport/Func.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.testsupport;\n\n/**\n *\n * @author freeman\n * @since 2021.0.1.0\n */\npublic interface Func {\n\n\t/**\n\t * just do, don't care the exception.\n\t * @throws Throwable e\n\t */\n\tvoid justDo() throws Throwable;\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/spring-cloud-alibaba-test-support/src/main/java/com/alibaba/cloud/testsupport/HasDockerAndItEnabled.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.testsupport;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\nimport org.junit.jupiter.api.extension.ExtendWith;\n\n/**\n * Disables test execution if Docker is unavailable.\n * <p>\n * We don't want to run integration tests on local machine, but still give a chance to run\n * it.\n * <p>\n * Typically, used for CI and local integration test.\n * <p>\n * Set system property\n * {@link HasDockerAndItEnabledCondition#RUN_INTEGRATION_TESTS_PROPERTY} to 'true'\n * <p>\n * general usage: {@code mvn -Dit.enabled=true test}\n * <p>\n * `it` means integration test\n *\n * @author freeman\n * @since 2021.0.1.0\n */\n@Target({ ElementType.TYPE, ElementType.METHOD })\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\n@ExtendWith(HasDockerAndItEnabledCondition.class)\npublic @interface HasDockerAndItEnabled {\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/spring-cloud-alibaba-test-support/src/main/java/com/alibaba/cloud/testsupport/HasDockerAndItEnabledCondition.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.testsupport;\n\nimport org.junit.jupiter.api.extension.ConditionEvaluationResult;\nimport org.junit.jupiter.api.extension.ExecutionCondition;\nimport org.junit.jupiter.api.extension.ExtensionContext;\nimport org.testcontainers.DockerClientFactory;\n\n/**\n * An {@link ExecutionCondition} that disables execution if Docker is unavailable.\n *\n * @author freeman\n * @since 2021.0.1.0\n */\nclass HasDockerAndItEnabledCondition implements ExecutionCondition {\n\n\tprivate static final String RUN_INTEGRATION_TESTS_PROPERTY = \"it.enabled\";\n\n\tprivate static final ConditionEvaluationResult ENABLED = ConditionEvaluationResult\n\t\t\t.enabled(\"Docker available.\");\n\n\tprivate static final ConditionEvaluationResult DISABLED = ConditionEvaluationResult\n\t\t\t.disabled(\"Default not run integration tests, you can set '\"\n\t\t\t\t\t+ RUN_INTEGRATION_TESTS_PROPERTY + \"=true' to enable.\");\n\n\tprivate static final ConditionEvaluationResult DOCKER_DISABLED = ConditionEvaluationResult\n\t\t\t.disabled(\"Docker unavailable.\");\n\n\t@Override\n\tpublic ConditionEvaluationResult evaluateExecutionCondition(\n\t\t\tExtensionContext context) {\n\t\ttry {\n\t\t\tif (Boolean\n\t\t\t\t\t.parseBoolean(System.getProperty(RUN_INTEGRATION_TESTS_PROPERTY))) {\n\t\t\t\tDockerClientFactory.instance().client();\n\t\t\t\treturn ENABLED;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn DISABLED;\n\t\t\t}\n\t\t}\n\t\tcatch (Throwable ignored) {\n\t\t\treturn DOCKER_DISABLED;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/spring-cloud-alibaba-test-support/src/main/java/com/alibaba/cloud/testsupport/InetUtil.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.testsupport;\n\nimport java.net.InetAddress;\nimport java.net.UnknownHostException;\n\n/**\n *\n * @author freeman\n * @since 2021.0.1.0\n */\npublic final class InetUtil {\n\n\t/**\n\t * Get host ip.\n\t *\n\t * <p>\n\t * It's very useful for the container test.\n\t *\n\t * @return host ip\n\t */\n\tpublic static String getHostIp() {\n\t\ttry {\n\t\t\treturn InetAddress.getLocalHost().getHostAddress();\n\t\t}\n\t\tcatch (UnknownHostException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\t/**\n\t * Get host name.\n\t *\n\t * @return host name\n\t */\n\tpublic static String getHostName() {\n\t\ttry {\n\t\t\treturn InetAddress.getLocalHost().getHostName();\n\t\t}\n\t\tcatch (UnknownHostException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/spring-cloud-alibaba-test-support/src/main/java/com/alibaba/cloud/testsupport/SpringCloudAlibaba.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.testsupport;\n\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Inherited;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\nimport org.junit.jupiter.api.MethodOrderer.OrderAnnotation;\nimport org.junit.jupiter.api.TestMethodOrder;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.testcontainers.junit.jupiter.Testcontainers;\n\n@Inherited\n@Testcontainers\n@Target(ElementType.TYPE)\n@Retention(RetentionPolicy.RUNTIME)\n@TestMethodOrder(OrderAnnotation.class)\n@ExtendWith(SpringCloudAlibabaExtension.class)\npublic @interface SpringCloudAlibaba {\n\tString[] composeFiles();\n\n\tString serviceName();\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/spring-cloud-alibaba-test-support/src/main/java/com/alibaba/cloud/testsupport/SpringCloudAlibabaExtension.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.testsupport;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.net.URL;\nimport java.time.Duration;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.extension.AfterAllCallback;\nimport org.junit.jupiter.api.extension.BeforeAllCallback;\nimport org.junit.jupiter.api.extension.BeforeEachCallback;\nimport org.junit.jupiter.api.extension.ExtensionContext;\nimport org.testcontainers.Testcontainers;\nimport org.testcontainers.containers.DockerComposeContainer;\nimport org.testcontainers.shaded.org.awaitility.Awaitility;\n\n@Slf4j\nfinal class SpringCloudAlibabaExtension\n\t\timplements BeforeAllCallback, AfterAllCallback, BeforeEachCallback {\n\tprivate final boolean LOCAL_MODE = Objects.equals(System.getProperty(\"local\"),\n\t\t\t\"true\");\n\n\tprivate DockerComposeContainer<?> compose;\n\n\t@Override\n\t@SuppressWarnings(\"UnstableApiUsage\")\n\tpublic void beforeAll(ExtensionContext context) throws IOException {\n\t\tAwaitility.setDefaultTimeout(Duration.ofSeconds(60));\n\t\tAwaitility.setDefaultPollInterval(Duration.ofSeconds(10));\n\n\t\tif (LOCAL_MODE) {\n\t\t\trunInLocal();\n\t\t}\n\t\telse {\n\t\t\trunInDockerContainer(context);\n\t\t}\n\t}\n\n\tprivate void runInLocal() {\n\t\tTestcontainers.exposeHostPorts(3000);\n\t}\n\n\tprivate void runInDockerContainer(ExtensionContext context) {\n\t\tcompose = createDockerCompose(context);\n\t\tcompose.start();\n\t}\n\n\t@Override\n\tpublic void afterAll(ExtensionContext context) {\n\t\tif (compose != null) {\n\t\t\tcompose.stop();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void beforeEach(ExtensionContext context) {\n\t\tfinal Object instance = context.getRequiredTestInstance();\n\t\tStream.of(instance.getClass().getDeclaredFields());\n\t}\n\n\tprivate DockerComposeContainer<?> createDockerCompose(ExtensionContext context) {\n\t\tfinal Class<?> clazz = context.getRequiredTestClass();\n\t\tfinal SpringCloudAlibaba annotation = clazz\n\t\t\t\t.getAnnotation(SpringCloudAlibaba.class);\n\t\tfinal List<File> files = Stream.of(annotation.composeFiles())\n\t\t\t\t.map(it -> SpringCloudAlibaba.class.getClassLoader().getResource(it))\n\t\t\t\t.filter(Objects::nonNull).map(URL::getPath).map(File::new)\n\t\t\t\t.collect(Collectors.toList());\n\t\tcompose = new DockerComposeContainer<>(files).withPull(true)\n\t\t\t\t.withTailChildContainers(true);\n\n\t\treturn compose;\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/spring-cloud-alibaba-test-support/src/main/java/com/alibaba/cloud/testsupport/TestExtend.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.testsupport;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\nimport org.junit.jupiter.api.extension.ExtendWith;\n\n@Target({ ElementType.TYPE, ElementType.METHOD })\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\n@ExtendWith(TestTimeoutExtension.class)\npublic @interface TestExtend {\n\n\tlong time();\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/spring-cloud-alibaba-test-support/src/main/java/com/alibaba/cloud/testsupport/TestTimeoutExtension.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.testsupport;\n\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\n\nimport org.junit.jupiter.api.extension.AfterAllCallback;\nimport org.junit.jupiter.api.extension.BeforeAllCallback;\nimport org.junit.jupiter.api.extension.BeforeEachCallback;\nimport org.junit.jupiter.api.extension.ExtensionContext;\n\npublic class TestTimeoutExtension\n\t\timplements BeforeAllCallback, BeforeEachCallback, AfterAllCallback {\n\n\t@Override\n\tpublic void afterAll(ExtensionContext context) throws Exception {\n\n\t}\n\n\t@Override\n\tpublic void beforeAll(ExtensionContext context) throws Exception {\n\n\t}\n\n\t@Override\n\tpublic void beforeEach(ExtensionContext context) throws Exception {\n\t\tfinal Class<?> clazz = context.getRequiredTestClass();\n\t\tfinal TestExtend annotation = clazz.getAnnotation(TestExtend.class);\n\t\tScheduledExecutorService singletonThread = Executors\n\t\t\t\t.newSingleThreadScheduledExecutor();\n\t\twhile (!singletonThread.awaitTermination(annotation.time(),\n\t\t\t\tTimeUnit.MILLISECONDS)) {\n\t\t\tsingletonThread.shutdown();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/spring-cloud-alibaba-test-support/src/main/java/com/alibaba/cloud/testsupport/Tester.java",
    "content": "/*\n * Copyright 2013-present the original author or 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\npackage com.alibaba.cloud.testsupport;\n\n/**\n *\n * @author freeman\n * @since 2021.0.1.0\n */\npublic class Tester {\n\n\t/**\n\t * Test function.\n\t * @param function function name\n\t * @param func func\n\t */\n\tpublic static void testFunction(String function, Func func) {\n\t\ttry {\n\t\t\tSystem.out.println(\n\t\t\t\t\t\"============================================================================\");\n\t\t\tSystem.out.println(\"Testing '\" + function + \"' ......\");\n\t\t\tSystem.out.println(\n\t\t\t\t\t\"============================================================================\");\n\n\t\t\tfunc.justDo();\n\n\t\t\tSystem.out.println(\n\t\t\t\t\t\"============================================================================\");\n\t\t\tSystem.out.println(\"Function '\" + function + \"' OK !\");\n\t\t\tSystem.out.println(\n\t\t\t\t\t\"============================================================================\\n\");\n\t\t}\n\t\tcatch (Throwable e) {\n\t\t\tSystem.err.println(\n\t\t\t\t\t\"============================================================================\");\n\t\t\tSystem.err.println(\"Function '\" + function + \"' err !\");\n\t\t\tSystem.err.println(\n\t\t\t\t\t\"============================================================================\\n\");\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\t/**\n\t * Do it, don't care exception.\n\t * @param func func\n\t */\n\tpublic static void justDo(Func func) {\n\t\ttry {\n\t\t\tfunc.justDo();\n\t\t}\n\t\tcatch (Throwable e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "spring-cloud-alibaba-tests/spring-cloud-alibaba-test-support/src/main/resources/rocketmq/conf/broker.conf",
    "content": "brokerClusterName = DefaultCluster\nbrokerName = broker-a\nbrokerId = 0\ndeleteWhen = 04\nfileReservedTime = 48\nbrokerRole = ASYNC_MASTER\nflushDiskType = ASYNC_FLUSH\n"
  }
]